Merge pull request #13 from github/mutation-example
Add mutation example
This commit is contained in:
Коммит
1339e974eb
2
Gemfile
2
Gemfile
|
@ -1,5 +1,5 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "rails", "~> 5.0.0"
|
||||
gem "rails", "~> 5.0.1"
|
||||
gem "graphql", "1.2.2"
|
||||
gem "graphql-client", "0.2.3"
|
||||
|
|
110
Gemfile.lock
110
Gemfile.lock
|
@ -1,106 +1,106 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
nio4r (~> 1.2)
|
||||
actioncable (5.0.3)
|
||||
actionpack (= 5.0.3)
|
||||
nio4r (>= 1.2, < 3.0)
|
||||
websocket-driver (~> 0.6.1)
|
||||
actionmailer (5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
actionview (= 5.0.0.1)
|
||||
activejob (= 5.0.0.1)
|
||||
actionmailer (5.0.3)
|
||||
actionpack (= 5.0.3)
|
||||
actionview (= 5.0.3)
|
||||
activejob (= 5.0.3)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.0.0.1)
|
||||
actionview (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
actionpack (5.0.3)
|
||||
actionview (= 5.0.3)
|
||||
activesupport (= 5.0.3)
|
||||
rack (~> 2.0)
|
||||
rack-test (~> 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
actionview (5.0.3)
|
||||
activesupport (= 5.0.3)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
activejob (5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
activejob (5.0.3)
|
||||
activesupport (= 5.0.3)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
activerecord (5.0.0.1)
|
||||
activemodel (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
activemodel (5.0.3)
|
||||
activesupport (= 5.0.3)
|
||||
activerecord (5.0.3)
|
||||
activemodel (= 5.0.3)
|
||||
activesupport (= 5.0.3)
|
||||
arel (~> 7.0)
|
||||
activesupport (5.0.0.1)
|
||||
activesupport (5.0.3)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
arel (7.1.4)
|
||||
builder (3.2.2)
|
||||
concurrent-ruby (1.0.2)
|
||||
builder (3.2.3)
|
||||
concurrent-ruby (1.0.5)
|
||||
erubis (2.7.0)
|
||||
globalid (0.3.7)
|
||||
activesupport (>= 4.1.0)
|
||||
globalid (0.4.0)
|
||||
activesupport (>= 4.2.0)
|
||||
graphql (1.2.2)
|
||||
graphql-client (0.2.3)
|
||||
activesupport (>= 3.0, < 6.0)
|
||||
graphql (>= 0.19.2)
|
||||
i18n (0.7.0)
|
||||
i18n (0.8.1)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.6.4)
|
||||
mail (2.6.5)
|
||||
mime-types (>= 1.16, < 4)
|
||||
method_source (0.8.2)
|
||||
mime-types (3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0521)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.9.1)
|
||||
nio4r (1.2.1)
|
||||
nokogiri (1.6.8.1)
|
||||
minitest (5.10.2)
|
||||
nio4r (2.0.0)
|
||||
nokogiri (1.7.2)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
rack (2.0.1)
|
||||
rack (2.0.3)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (5.0.0.1)
|
||||
actioncable (= 5.0.0.1)
|
||||
actionmailer (= 5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
actionview (= 5.0.0.1)
|
||||
activejob (= 5.0.0.1)
|
||||
activemodel (= 5.0.0.1)
|
||||
activerecord (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
rails (5.0.3)
|
||||
actioncable (= 5.0.3)
|
||||
actionmailer (= 5.0.3)
|
||||
actionpack (= 5.0.3)
|
||||
actionview (= 5.0.3)
|
||||
activejob (= 5.0.3)
|
||||
activemodel (= 5.0.3)
|
||||
activerecord (= 5.0.3)
|
||||
activesupport (= 5.0.3)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 5.0.0.1)
|
||||
railties (= 5.0.3)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-dom-testing (2.0.1)
|
||||
activesupport (>= 4.2.0, < 6.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
railties (5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
railties (5.0.3)
|
||||
actionpack (= 5.0.3)
|
||||
activesupport (= 5.0.3)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (11.3.0)
|
||||
sprockets (3.7.0)
|
||||
rake (12.0.0)
|
||||
sprockets (3.7.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.2.0)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
tzinfo (1.2.2)
|
||||
thor (0.19.4)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.3)
|
||||
thread_safe (~> 0.1)
|
||||
websocket-driver (0.6.4)
|
||||
websocket-driver (0.6.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.2)
|
||||
|
||||
|
@ -110,7 +110,7 @@ PLATFORMS
|
|||
DEPENDENCIES
|
||||
graphql (= 1.2.2)
|
||||
graphql-client (= 0.2.3)
|
||||
rails (~> 5.0.0)
|
||||
rails (~> 5.0.1)
|
||||
|
||||
BUNDLED WITH
|
||||
1.13.6
|
||||
1.14.6
|
||||
|
|
|
@ -117,4 +117,60 @@ class RepositoriesController < ApplicationController
|
|||
head :not_found
|
||||
end
|
||||
end
|
||||
|
||||
StarMutation = GitHub::Client.parse <<-'GRAPHQL'
|
||||
mutation($id: ID!) {
|
||||
star(input: { starrableId: $id }) {
|
||||
starrable {
|
||||
...Views::Repositories::Star::Repository
|
||||
}
|
||||
}
|
||||
}
|
||||
GRAPHQL
|
||||
|
||||
def star
|
||||
data = query StarMutation, id: params[:id]
|
||||
|
||||
if repository = data.star
|
||||
respond_to do |format|
|
||||
format.js {
|
||||
render partial: "repositories/star", locals: { repository: data.star.starrable }
|
||||
}
|
||||
|
||||
format.html {
|
||||
redirect_to "/repositories"
|
||||
}
|
||||
end
|
||||
else
|
||||
head :not_found
|
||||
end
|
||||
end
|
||||
|
||||
UnstarMutation = GitHub::Client.parse <<-'GRAPHQL'
|
||||
mutation($id: ID!) {
|
||||
unstar(input: { starrableId: $id }) {
|
||||
starrable {
|
||||
...Views::Repositories::Star::Repository
|
||||
}
|
||||
}
|
||||
}
|
||||
GRAPHQL
|
||||
|
||||
def unstar
|
||||
data = query UnstarMutation, id: params[:id]
|
||||
|
||||
if repository = data.unstar
|
||||
respond_to do |format|
|
||||
format.js {
|
||||
render partial: "repositories/star", locals: { repository: data.unstar.starrable }
|
||||
}
|
||||
|
||||
format.html {
|
||||
redirect_to "/repositories"
|
||||
}
|
||||
end
|
||||
else
|
||||
head :not_found
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,16 +9,13 @@
|
|||
totalCount
|
||||
}
|
||||
...Views::Repositories::Icon::Repository
|
||||
...Views::Repositories::Star::Repository
|
||||
}
|
||||
%>
|
||||
<% repository = Views::Repositories::ListItem::Repository.new(repository) %>
|
||||
|
||||
<li class="list-group-item">
|
||||
<span class="star-badge">
|
||||
<%= repository.stargazers.total_count %>
|
||||
<span class="octicon octicon-star"></span>
|
||||
</span>
|
||||
|
||||
<%= render "repositories/star", repository: repository %>
|
||||
<%= render "repositories/icon", repository: repository %>
|
||||
|
||||
<a href="<%= repository_path(repository.id) %>">
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
<% if repositories.page_info.has_next_page? %>
|
||||
<li class="list-group-item show-more">
|
||||
<a onclick="loadMoreRepositories(event);" href="<%= more_repositories_path(after: repositories.edges.last.cursor) %>">
|
||||
<a class="js-load-more" href="<%= more_repositories_path(after: repositories.edges.last.cursor) %>">
|
||||
Show more repositories...
|
||||
</a>
|
||||
<span class="octicon octicon-sync spinner"></span>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<%graphql
|
||||
fragment Repository on Repository {
|
||||
id
|
||||
viewerHasStarred
|
||||
stargazers {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
%>
|
||||
<% repository = Views::Repositories::Star::Repository.new(repository) %>
|
||||
|
||||
<span class="star-badge">
|
||||
<%= repository.stargazers.total_count %>
|
||||
<%= form_tag repository.viewer_has_starred? ? unstar_repository_path(repository.id) : star_repository_path(repository.id), method: :put, class: "star-form" do %>
|
||||
<button>
|
||||
<span class="octicon octicon-star <% if repository.viewer_has_starred? %>highlight<% end %>"></span>
|
||||
</button>
|
||||
<% end %>
|
||||
</span>
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
# Include repositories/_navigation.html.erb data dependencies
|
||||
...Views::Repositories::Navigation::Repository
|
||||
|
||||
...Views::Repositories::Star::Repository
|
||||
}
|
||||
%>
|
||||
<%#
|
||||
|
@ -55,11 +57,15 @@
|
|||
<div class="header clearfix">
|
||||
<%= render "repositories/navigation", repository: repository %>
|
||||
|
||||
<h3 class="text-muted">
|
||||
<h3 class="text-muted inline-block">
|
||||
<a href="<%= repositories_path %>"><%= repository.owner.login %></a>
|
||||
/
|
||||
<a href="<%= repository_path(repository.id) %>"><%= repository.name %></a>
|
||||
</h3>
|
||||
|
||||
<div class="inline-block star-badge-header">
|
||||
<%= render "repositories/star", repository: repository %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
Rails.application.routes.draw do
|
||||
resources :repositories do
|
||||
get "more", on: :collection
|
||||
put "star", on: :member
|
||||
put "unstar", on: :member
|
||||
end
|
||||
get "/", to: redirect("/repositories")
|
||||
end
|
||||
|
|
40907
db/schema.json
40907
db/schema.json
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -3,6 +3,10 @@ body {
|
|||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
@ -27,6 +31,30 @@ body {
|
|||
color: #777;
|
||||
}
|
||||
|
||||
.star-badge-header {
|
||||
margin-left: 10px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.star-badge .octicon {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.star-badge .highlight {
|
||||
color: #e36209;
|
||||
}
|
||||
|
||||
.star-form {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.star-form button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-pills .badge {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,40 @@
|
|||
function loadMoreRepositories(event) {
|
||||
var container = event.target.parentElement;
|
||||
function loadMoreRepositories(link) {
|
||||
var container = link.parentElement;
|
||||
container.classList.add('loading');
|
||||
event.preventDefault();
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', event.target.href, true);
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
xhr.onload = function() {
|
||||
container.insertAdjacentHTML('afterend', xhr.responseText);
|
||||
container.remove();
|
||||
}
|
||||
xhr.send();
|
||||
fetch(link.href).then(function(response) {
|
||||
response.text().then(function(text) {
|
||||
container.insertAdjacentHTML('afterend', text);
|
||||
container.remove();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function toggleStar(el) {
|
||||
fetch(el.action, { method: 'PUT', headers: { 'X-Requested-With': 'XMLHttpRequest' } }).then(function(response) {
|
||||
response.text().then(function(text) {
|
||||
// Parse text to get an actual element
|
||||
var div = document.createElement('div')
|
||||
div.innerHTML = text
|
||||
|
||||
// Find the star container
|
||||
var container = el.closest('.star-badge')
|
||||
container.replaceWith(div.firstElementChild)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
document.addEventListener('submit', function(e) {
|
||||
var form = e.target
|
||||
toggleStar(form)
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
// Basic event delegation
|
||||
document.addEventListener('click', function(e) {
|
||||
var loadMoreLink = e.target.closest('.js-load-more')
|
||||
if (loadMoreLink) {
|
||||
loadMoreRepositories(loadMoreLink)
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
|
|
Загрузка…
Ссылка в новой задаче