Skip to content

Commit c4a0fdf

Browse files
committed
add admin views for questions
1 parent ac7f034 commit c4a0fdf

File tree

19 files changed

+286
-1
lines changed

19 files changed

+286
-1
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//= require spree/backend/models/answer
2+
3+
Spree.Collections.Answers = Backbone.Collection.extend({
4+
model: Spree.Models.Answer,
5+
6+
url: function() {
7+
return this.parent.url() + '/answers';
8+
}
9+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//= require spree/backend/models/question
2+
3+
Spree.Collections.Questions = Backbone.Collection.extend({
4+
model: Spree.Models.Question
5+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Spree.Models.Answer = Backbone.Model.extend({
2+
paramRoot: 'answer',
3+
urlRoot: function() {
4+
return Spree.pathFor('api/questions/' + this.get('question_id') + '/answers');
5+
}
6+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//=require spree/backend/collections/answers
2+
3+
Spree.Models.Question = Backbone.Model.extend({
4+
urlRoot: Spree.pathFor('api/questions'),
5+
6+
relations: {
7+
'answers': Spree.Collections.Answers
8+
}
9+
});
10+
11+
Spree.Models.Question.fetch = function(id, opts) {
12+
const options = (opts || {});
13+
const model = new Spree.Models.Question({
14+
id: id,
15+
answers: []
16+
});
17+
model.fetch(options);
18+
return model;
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//= require spree/backend/models/question
2+
//= require spree/backend/views/questions/modal-content
3+
4+
Spree.ready(function() {
5+
if ($('.question-modal-content').length) {
6+
$('.question-modal-content').each(function() {
7+
var el = $(this);
8+
var model = new Spree.Models.Question.fetch(el.data('question_id'));
9+
new Spree.Views.Questions.ModalContent({
10+
el: el,
11+
model: model
12+
})
13+
});
14+
}
15+
});

app/assets/javascripts/spree/backend/solidus_marketplace.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
// Shipments AJAX API
33

44
//= require spree/backend/solidus_marketplace_routes
5-
//= require spree/backend/suppliers_autocomplete
5+
//= require spree/backend/suppliers_autocomplete
6+
//= require spree/backend/questions
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class='alert alert-secondary'>
2+
{{answer.answer_text}}
3+
<p class='font-italic'>{{answer.user.email}} - {{answer.created_at}}</p>
4+
</div>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<input class='answer-input' />
2+
<button class='btn btn-primary submit'>{{ t 'create' }}</button>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class='answers'>
2+
</div>
3+
<div class='new-answer'>
4+
</div>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//= require spree/backend/templates/answers/answer-item
2+
3+
Spree.Views.Answers.AnswerItem = Backbone.View.extend({
4+
initialize: function(options) {
5+
this.listenTo(this.model, 'change', this.render);
6+
},
7+
8+
template: HandlebarsTemplates['answers/answer-item'],
9+
10+
render: function() {
11+
this.$el.html(this.template({
12+
answer: this.model.toJSON()
13+
}));
14+
}
15+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//= require spree/backend/views/answers/answer-item
2+
3+
Spree.Views.Answers.AnswerList = Backbone.View.extend({
4+
initialize: function() {
5+
this.listenTo(this.collection, 'add', this.add);
6+
this.listenTo(this.collection, 'reset', this.reset);
7+
},
8+
9+
add: function(answer) {
10+
var view = new Spree.Views.Answers.AnswerItem({model: answer});
11+
view.render();
12+
this.$el.append(view.el);
13+
},
14+
15+
reset: function() {
16+
const add = this.add;
17+
this.collection.each(function(answer) {
18+
add(answer)
19+
})
20+
}
21+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//= require spree/backend/templates/answers/new
2+
//= require spree/backend/models/answer
3+
4+
Spree.Views.Answers ||= {};
5+
6+
Spree.Views.Answers.New = Backbone.View.extend({
7+
initialize: function() {
8+
this.listenTo(this.collection, 'update', this.render)
9+
this.render();
10+
},
11+
12+
template: HandlebarsTemplates['answers/new'],
13+
14+
events: {
15+
'click .submit': 'onSubmit'
16+
},
17+
18+
onSubmit: function(e) {
19+
e.preventDefault();
20+
const input = $('.answer-input')
21+
const options = {
22+
success: this.onSuccess.bind(this),
23+
error: this.onError.bind(this)
24+
};
25+
this.collection.create({
26+
answer_text: input.val(),
27+
question_id: this.collection.parent.id
28+
}, options)
29+
input.val('');
30+
},
31+
32+
onSuccess: function() {
33+
show_flash("success", Spree.translations.created_successfully);
34+
},
35+
36+
onError: function(model, response, options) {
37+
show_flash("error", response.responseText);
38+
},
39+
40+
render: function() {
41+
this.$el.html(this.template());
42+
}
43+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//= require spree/backend/templates/questions/modal-content
2+
//= require spree/backend/views/answers/new
3+
//= require spree/backend/views/answers/answer-list
4+
5+
Spree.Views.Questions ||= {}
6+
7+
Spree.Views.Questions.ModalContent = Backbone.View.extend({
8+
initialize: function(options){
9+
this.render();
10+
},
11+
template: HandlebarsTemplates['questions/modal-content'],
12+
13+
render: function() {
14+
this.$el.html(this.template());
15+
const collection = this.model.get('answers');
16+
17+
new Spree.Views.Answers.AnswerList({
18+
el: $('.answers'),
19+
parent: this.model,
20+
collection: collection
21+
});
22+
new Spree.Views.Answers.New({
23+
el: $('.new-answer'),
24+
collection: collection
25+
});
26+
}
27+
});

config/locales/en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,6 @@ en:
128128
user_admin: Admin User
129129
remove_payment_method: Remove payment method
130130
add_payment_method: Add payment method
131+
questions:
132+
title: Questions
133+
reply: Reply

config/locales/es.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,6 @@ es:
125125
user_admin: Usuario administrador
126126
remove_payment_method: Remover método de pago
127127
add_payment_method: Agregar método de pago
128+
questions:
129+
title: Preguntas
130+
reply: Contestar
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# frozen_string_literal: true
2+
3+
module Spree
4+
module Admin
5+
class QuestionsController < BaseController
6+
def index
7+
params[:q] ||= {}
8+
@search = Spree::Question.accessible_by(current_ability, :index)
9+
.ransack(params[:q])
10+
@questions = @search.result
11+
.page(params[:page])
12+
.per(params[:per_page] || Spree::Config[:orders_per_page])
13+
end
14+
end
15+
end
16+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<div class="modal fade" id="<%= target %>" role="dialog" aria-labelledby="<%= target %>" aria-hidden="true">
2+
<div class="modal-dialog" role="document">
3+
<div class="modal-content">
4+
<div class="modal-header">
5+
<h5 class="modal-title" id="<%= target %>"><%= question.question_text %></h5>
6+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
7+
<span aria-hidden="true">&times;</span>
8+
</button>
9+
</div>
10+
<div class="modal-body">
11+
<div class='question-modal-content' data-question_id='<%= question.id %>'></div>
12+
</div>
13+
</div>
14+
</div>
15+
</div>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<% admin_layout "full-width" %>
2+
3+
<% admin_breadcrumb(plural_resource_name(Spree::Question)) %>
4+
5+
<%= paginate @questions, theme: "solidus_admin" %>
6+
<% if @questions.any? %>
7+
<table class="index" id="listing_questions" data-hook>
8+
<thead>
9+
<tr data-hook="admin_questions_index_headers">
10+
<th><%= sort_link @search, :question_text %></th>
11+
<th><%= sort_link @search, :created_at %></th>
12+
<th><%= sort_link @search, :created_by %></th>
13+
<th><%= sort_link @search, :published %></th>
14+
<th><%= sort_link @search, :resolved %></th>
15+
</tr>
16+
</thead>
17+
<tbody>
18+
<% @questions.each do |question| %>
19+
<tr class='question' data-id='<%= question.id %>'>
20+
<td><%= question.question_text %></td>
21+
<td><%= question.created_at %></td>
22+
<td><%= question.created_by.email %></td>
23+
<td><%= question.published %></td>
24+
<td><%= question.resolved %></td>
25+
<td><%= link_to t('spree.questions.reply'), '#', class: 'btn btn-primary', data: { toggle: 'modal', target: "#modal-question#{question.id}"} %></td>
26+
</tr>
27+
<%= render 'question_modal',
28+
question: question,
29+
target: "modal-question#{question.id}"
30+
%>
31+
<% end %>
32+
</tbody>
33+
<% else %>
34+
<div class="no-objects-found">
35+
<% if can? :manage, Spree::Question %>
36+
<%= render 'spree/admin/shared/no_objects_found',
37+
resource: Spree::Question %>
38+
<% end %>
39+
</div>
40+
<% end %>
41+
<%= paginate @questions, theme: "solidus_admin" %>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
5+
describe 'Questions admin page', type: :feature, js: true do
6+
stub_authorization!
7+
8+
let(:user) { create(:supplier_admin) }
9+
let(:supplier) { create(:supplier, admins: [user]) }
10+
let!(:question) { create(:question, supplier: supplier, question_text: 'How much?') }
11+
let!(:answer) { create(:answer, question: question, user: user, answer_text: 'Answer0') }
12+
13+
before do
14+
visit spree.admin_questions_path
15+
end
16+
17+
it 'render supplier questions' do
18+
expect(page).to have_content('How much?')
19+
end
20+
21+
context 'with modal' do
22+
before do
23+
click_on('Reply')
24+
end
25+
26+
it 'show answers' do
27+
expect(page).to have_content('Answer0')
28+
end
29+
30+
it 'allow reply question' do
31+
find('.answer-input').fill_in with: 'Answer1'
32+
click_on('Create')
33+
expect(page).to have_content('Answer1')
34+
end
35+
end
36+
end

0 commit comments

Comments
 (0)