Merge pull request #13 from github/mutation-example

Add mutation example
This commit is contained in:
Joshua Peek 2018-05-02 12:55:43 -07:00 коммит произвёл GitHub
Родитель 69df59af9e c4aa54a999
Коммит 1339e974eb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 28309 добавлений и 12880 удалений

Просмотреть файл

@ -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"

Просмотреть файл

@ -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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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()
}
})