├── .gitignore ├── .gitmodules ├── .rspec ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ └── application.js │ └── stylesheets │ │ └── application.css.scss ├── controllers │ ├── admin │ │ ├── documents_controller.rb │ │ ├── pictures_controller.rb │ │ ├── sidekiq_controller.rb │ │ ├── users_controller.rb │ │ └── web_hooks_controller.rb │ ├── application_controller.rb │ ├── concerns │ │ └── .keep │ ├── documents_controller.rb │ ├── pictures_controller.rb │ ├── record_controller.rb │ ├── templates_controller.rb │ └── top_controller.rb ├── helpers │ ├── application_helper.rb │ └── devise_helper.rb ├── jobs │ ├── file_job.rb │ └── web_hook_job.rb ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── concerns │ │ ├── .keep │ │ └── grade.rb │ ├── document.rb │ ├── picture.rb │ ├── template.rb │ ├── user.rb │ ├── user_document.rb │ └── web_hook.rb └── views │ ├── admin │ ├── documents │ │ ├── _list.html.slim │ │ ├── _modal.html.slim │ │ └── show.js.coffee │ ├── pictures │ │ ├── _delete.html.slim │ │ ├── _list.html.slim │ │ ├── _modal.html.slim │ │ ├── delete.js.coffee │ │ ├── index.html.slim │ │ └── show.js.coffee │ ├── sidekiq │ │ └── index.html.slim │ ├── users │ │ ├── _delete.html.slim │ │ ├── _form.html.slim │ │ ├── _list.html.slim │ │ ├── delete.js.coffee │ │ ├── edit.js.coffee │ │ ├── index.html.slim │ │ ├── new.js.coffee │ │ ├── show.html.slim │ │ └── submit.js.coffee │ └── web_hooks │ │ ├── _delete.html.slim │ │ ├── _form.html.slim │ │ ├── _list.html.slim │ │ ├── delete.js.coffee │ │ ├── edit.js.coffee │ │ ├── index.html.slim │ │ ├── new.js.coffee │ │ └── submit.js.coffee │ ├── devise │ ├── mailer │ │ └── reset_password_instructions.html.slim │ ├── passwords │ │ ├── edit.html.slim │ │ └── new.html.slim │ ├── registrations │ │ └── edit.html.slim │ └── sessions │ │ └── new.html.slim │ ├── documents │ ├── _delete.html.slim │ ├── _dropdown.html.slim │ ├── _form.html.slim │ ├── _list.html.slim │ ├── _sidebar.html.slim │ ├── delete.js.coffee │ ├── edit.html.slim │ ├── index.html.slim │ ├── new.html.slim │ ├── show.html.slim │ └── submit.js.coffee │ ├── error │ └── _form.html.slim │ ├── kaminari │ ├── _first_page.html.erb │ ├── _gap.html.erb │ ├── _last_page.html.erb │ ├── _next_page.html.erb │ ├── _page.html.erb │ ├── _paginator.html.erb │ └── _prev_page.html.erb │ ├── layouts │ └── application.html.slim │ ├── record │ ├── _dropdown.html.slim │ ├── _sidebar.html.slim │ └── index.html.slim │ ├── templates │ ├── _delete.html.slim │ ├── _form.html.slim │ ├── _list.html.slim │ ├── delete.js.coffee │ ├── edit.html.slim │ ├── index.html.slim │ ├── new.html.slim │ ├── select.js.coffee │ ├── show.html.slim │ └── submit.js.coffee │ └── top │ └── index.html.slim ├── bin ├── bundle ├── rails ├── rake ├── setup └── unicorn.j2 ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── events.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── devise.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── multi_json.rb │ ├── session_store.rb │ ├── sidekiq.rb │ ├── websocket_rails.rb │ └── wrap_parameters.rb ├── locales │ ├── devise.en.yml │ ├── devise.ja.yml │ ├── en.yml │ └── ja.yml ├── nginx.j2 ├── routes.rb ├── secrets.yml ├── sidekiq.yml └── unicorn.rb ├── db ├── migrate │ ├── 20150109064610_devise_create_users.rb │ ├── 20150109120407_create_documents.rb │ ├── 20150109120656_create_user_documents.rb │ ├── 20150206085547_create_templates.rb │ ├── 20150303012227_create_pictures.rb │ ├── 20150303112317_add_admin_flag_to_users.rb │ ├── 20150409102507_add_grade_to_users.rb │ ├── 20150409141425_add_name_and_pattern_to_templtates.rb │ ├── 20150416101206_recoverable_users.rb │ ├── 20150422123551_create_web_hooks.rb │ └── 20150907074242_add_name_to_web_hooks.rb ├── schema.rb └── seeds.rb ├── lib ├── assets │ └── .keep ├── gitlab │ ├── popen.rb │ └── sidekiq_memory_killer.rb └── tasks │ ├── .keep │ ├── ansible.rake │ └── sidekiq.rake ├── log └── .keep ├── public ├── 404.html ├── 422.html ├── 500.html ├── fonts │ ├── logo_type_gothic.eot │ ├── logo_type_gothic.ttf │ └── logo_type_gothic.woff ├── images │ └── favicon.ico └── robots.txt ├── spec ├── controllers │ ├── admin │ │ ├── documents_controller_spec.rb │ │ ├── pictures_controller_spec.rb │ │ ├── sidekiq_controller_spec.rb │ │ ├── users_controller_spec.rb │ │ └── web_hooks_controller_spec.rb │ ├── documents_controller_spec.rb │ ├── pictures_controller_spec.rb │ ├── record_controller_spec.rb │ ├── templates_controller_spec.rb │ └── top_controller_spec.rb ├── factories │ ├── documents.rb │ ├── pictures.rb │ ├── templates.rb │ ├── user_documents.rb │ ├── users.rb │ └── web_hooks.rb ├── jobs │ ├── file_job_spec.rb │ └── web_hook_job_spec.rb ├── models │ ├── document_spec.rb │ ├── picture_spec.rb │ ├── template_spec.rb │ ├── user_document_spec.rb │ ├── user_spec.rb │ └── web_hook_spec.rb ├── rails_helper.rb └── spec_helper.rb └── vendor └── assets ├── javascripts ├── .keep ├── codemirror │ ├── addon │ │ └── mode │ │ │ └── overlay.js │ ├── codemirror.js │ └── mode │ │ ├── gfm │ │ └── gfm.js │ │ ├── markdown │ │ └── markdown.js │ │ └── xml │ │ └── xml.js ├── highlight │ └── highlight.min.js ├── marked │ └── marked.min.js └── uikit │ ├── components │ ├── accordion.min.js │ ├── autocomplete.min.js │ ├── datepicker.min.js │ ├── form-password.min.js │ ├── form-select.min.js │ ├── grid.min.js │ ├── htmleditor.min.js │ ├── lightbox.min.js │ ├── nestable.min.js │ ├── notify.min.js │ ├── pagination.min.js │ ├── parallax.min.js │ ├── search.min.js │ ├── slider.min.js │ ├── slideset.min.js │ ├── slideshow-fx.min.js │ ├── slideshow.min.js │ ├── sortable.min.js │ ├── sticky.min.js │ ├── timepicker.min.js │ ├── tooltip.min.js │ └── upload.min.js │ ├── core │ ├── alert.min.js │ ├── button.min.js │ ├── core.min.js │ ├── cover.min.js │ ├── dropdown.min.js │ ├── grid.min.js │ ├── modal.min.js │ ├── nav.min.js │ ├── offcanvas.min.js │ ├── scrollspy.min.js │ ├── smooth-scroll.min.js │ ├── switcher.min.js │ ├── tab.min.js │ ├── toggle.min.js │ ├── touch.min.js │ └── utility.min.js │ └── uikit.min.js └── stylesheets ├── .keep ├── codemirror └── codemirror.css ├── highlight └── tomorrow.css └── uikit ├── components ├── accordion.almost-flat.min.css ├── autocomplete.almost-flat.min.css ├── datepicker.almost-flat.min.css ├── dotnav.almost-flat.min.css ├── form-advanced.almost-flat.min.css ├── form-file.almost-flat.min.css ├── form-password.almost-flat.min.css ├── form-select.almost-flat.min.css ├── htmleditor.almost-flat.min.css ├── nestable.almost-flat.min.css ├── notify.almost-flat.min.css ├── placeholder.almost-flat.min.css ├── progress.almost-flat.min.css ├── search.almost-flat.min.css ├── slidenav.almost-flat.min.css ├── slider.almost-flat.min.css ├── slideshow.almost-flat.min.css ├── sortable.almost-flat.min.css ├── sticky.almost-flat.min.css ├── tooltip.almost-flat.min.css └── upload.almost-flat.min.css └── uikit.almost-flat.min.css /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | /vendor/bundler 10 | /vendor/bin 11 | 12 | # Ignore the default SQLite database. 13 | /db/*.sqlite3 14 | /db/*.sqlite3-journal 15 | 16 | # Ignore all logfiles and tempfiles. 17 | /log/*.log 18 | /tmp 19 | 20 | # Ignore editor swap files. 21 | *~ 22 | .*.swp 23 | *#* 24 | 25 | # Ignore assets pipeline files. 26 | /public/assets 27 | 28 | /public/pictures 29 | /public/documents 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "playbook"] 2 | path = playbook 3 | url = https://github.com/hico-horiuchi/ansible-rails-deploy.git 4 | [submodule "vendor/assets/stylesheets/github-markdown-css"] 5 | path = vendor/assets/stylesheets/github-markdown-css 6 | url = https://github.com/sindresorhus/github-markdown-css.git 7 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | ruby '2.2.3' 3 | 4 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 5 | gem 'rails', '4.2.3' 6 | # Use postgresql as the database for Active Record 7 | gem 'pg' 8 | # Use SCSS for stylesheets 9 | gem 'sass-rails', '~> 5.0' 10 | # Use Uglifier as compressor for JavaScript assets 11 | gem 'uglifier', '>= 1.3.0' 12 | # Use CoffeeScript for .coffee assets and views 13 | gem 'coffee-rails', '~> 4.1.0' 14 | # See https://github.com/sstephenson/execjs#readme for more supported runtimes 15 | gem 'therubyracer', platforms: :ruby 16 | # Use jquery as the JavaScript library 17 | gem 'jquery-rails' 18 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 19 | gem 'turbolinks' 20 | # jQuery plugin for drop-in fix binded events problem caused by Turbolinks 21 | gem 'jquery-turbolinks' 22 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 23 | gem 'jbuilder', '~> 2.0' 24 | # Use ActiveModel has_secure_password 25 | # gem 'bcrypt', '~> 3.1.7' 26 | 27 | group :doc do 28 | # bundle exec rake doc:rails generates the API under doc/api. 29 | gem 'sdoc', '~> 0.4.0' 30 | end 31 | 32 | group :development do 33 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 34 | gem 'spring' 35 | # Use Capistrano for deployment 36 | # gem 'capistrano-rails' 37 | gem 'annotate' 38 | gem 'quiet_assets' 39 | end 40 | 41 | group :development, :test do 42 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 43 | # gem 'byebug' 44 | # Access an IRB console on exception pages or by using <%= console %> in views 45 | # gem 'web-console', '~> 2.0' 46 | gem 'pry-rails' 47 | gem 'rspec-rails' 48 | gem 'factory_girl_rails' 49 | gem 'better_errors' 50 | gem 'binding_of_caller' 51 | end 52 | 53 | group :production do 54 | # Use unicorn as the app server 55 | gem 'unicorn' 56 | gem 'unicorn-worker-killer' 57 | end 58 | 59 | gem 'yajl-ruby' 60 | gem 'devise' 61 | gem 'slim-rails' 62 | gem 'font-awesome-rails' 63 | gem 'kaminari' 64 | gem 'paperclip' 65 | gem 'websocket-rails' 66 | gem 'sidekiq' 67 | gem 'sinatra', require: false 68 | gem 'rmagick' 69 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sai-lab/shoko/bbe01346c725ee7342956c57f2295ce1e44636d6/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery 14 | //= require jquery.turbolinks 15 | //= require jquery_ujs 16 | //= require uikit/uikit.min 17 | //= require uikit/components/datepicker.min 18 | //= require uikit/components/htmleditor.min 19 | //= require uikit/components/notify.min 20 | //= require uikit/components/tooltip.min 21 | //= require uikit/components/upload.min 22 | //= require codemirror/codemirror 23 | //= require codemirror/mode/markdown/markdown 24 | //= require codemirror/mode/xml/xml 25 | //= require codemirror/mode/gfm/gfm 26 | //= require codemirror/addon/mode/overlay 27 | //= require marked/marked.min 28 | //= require highlight/highlight.min 29 | //= require websocket_rails/main 30 | //= require turbolinks 31 | -------------------------------------------------------------------------------- /app/controllers/admin/documents_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::DocumentsController < ApplicationController 2 | before_action :authenticate_user! 3 | before_action :admin_user! 4 | before_action :load_document 5 | 6 | def show 7 | end 8 | 9 | private 10 | 11 | def load_document 12 | @document = Document.id_is(params[:id]) if params[:id] 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/controllers/admin/pictures_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::PicturesController < ApplicationController 2 | before_action :authenticate_user! 3 | before_action :admin_user! 4 | before_action :load_picture 5 | 6 | def index 7 | @pictures = Picture.order(updated_at: :desc).page(params[:page]).per(20) 8 | end 9 | 10 | def show 11 | end 12 | 13 | def delete 14 | end 15 | 16 | def destroy 17 | @result = @picture.destroy 18 | 19 | if @result 20 | flash[:notice] = '画像を削除しました。' 21 | else 22 | flash[:alert] = '画像を削除できませんでした。' 23 | end 24 | 25 | redirect_to admin_pictures_path 26 | end 27 | 28 | private 29 | 30 | def load_picture 31 | @picture = Picture.id_is(params[:id]) if params[:id] 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /app/controllers/admin/sidekiq_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::SidekiqController < ApplicationController 2 | before_action :authenticate_user! 3 | before_action :admin_user! 4 | 5 | def index 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/admin/users_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::UsersController < ApplicationController 2 | before_action :authenticate_user! 3 | before_action :admin_user! 4 | before_action :load_user 5 | 6 | def index 7 | @users = User.order(updated_at: :desc).page(params[:page]).per(20) 8 | end 9 | 10 | def show 11 | @documents = @user.documents.order(updated_at: :desc).page(params[:page]).per(20) 12 | end 13 | 14 | def new 15 | @user = User.new 16 | end 17 | 18 | def create 19 | @user = User.new user_params 20 | @result = @user.save 21 | flash[:notice] = 'ユーザーを作成しました。' if @result 22 | render :submit 23 | end 24 | 25 | def edit 26 | end 27 | 28 | def update 29 | @result = @user.update_without_current_password user_params 30 | flash[:notice] = 'ユーザーを更新しました。' if @result 31 | render :submit 32 | end 33 | 34 | def delete 35 | end 36 | 37 | def destroy 38 | @result = @user.destroy 39 | 40 | if @result 41 | flash[:notice] = 'ユーザーを削除しました。' 42 | else 43 | flash[:alert] = 'ユーザーを削除できませんでした。' 44 | end 45 | 46 | redirect_to admin_users_path 47 | end 48 | 49 | private 50 | 51 | def load_user 52 | @user = User.id_is(params[:id]) if params[:id] 53 | end 54 | 55 | def user_params 56 | params.require(:user).permit :email, :name, :grade, :password, :password_confirmation, :admin_flag 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /app/controllers/admin/web_hooks_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::WebHooksController < ApplicationController 2 | before_action :authenticate_user! 3 | before_action :admin_user! 4 | before_action :load_web_hook 5 | 6 | def index 7 | @web_hooks = WebHook.order(updated_at: :desc).page(params[:page]).per(20) 8 | end 9 | 10 | def show 11 | end 12 | 13 | def new 14 | @web_hook = WebHook.new 15 | end 16 | 17 | def create 18 | @web_hook = WebHook.new web_hook_params 19 | @result = @web_hook.save 20 | flash[:notice] = 'WebHookを作成しました。' if @result 21 | render :submit 22 | end 23 | 24 | def edit 25 | end 26 | 27 | def update 28 | @result = @web_hook.update web_hook_params 29 | flash[:notice] = 'WebHookを更新しました。' if @result 30 | render :submit 31 | end 32 | 33 | def delete 34 | end 35 | 36 | def destroy 37 | @result = @web_hook.destroy 38 | 39 | if @result 40 | flash[:notice] = 'WebHookを削除しました。' 41 | else 42 | flash[:alert] = 'WebHookを削除できませんでした。' 43 | end 44 | 45 | redirect_to admin_web_hooks_path 46 | end 47 | 48 | private 49 | 50 | def load_web_hook 51 | @web_hook = WebHook.id_is(params[:id]) if params[:id] 52 | end 53 | 54 | def web_hook_params 55 | params.require(:web_hook).permit :name, :url 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | before_action :configure_permitted_parameters, if: :devise_controller? 6 | 7 | def admin_user! 8 | unless current_user.is_admin? 9 | render file: "#{Rails.root}/public/404.html", layout: false, status: 404 10 | end 11 | end 12 | 13 | def configure_permitted_parameters 14 | devise_parameter_sanitizer.for(:account_update) << [:email, :name] 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sai-lab/shoko/bbe01346c725ee7342956c57f2295ce1e44636d6/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/documents_controller.rb: -------------------------------------------------------------------------------- 1 | class DocumentsController < ApplicationController 2 | before_action :authenticate_user! 3 | before_action :load_document 4 | 5 | def index 6 | @users = User.all 7 | 8 | if params[:user].present? 9 | @documents = User.id_is(params[:user]).documents 10 | else 11 | @documents = Document.all 12 | end 13 | 14 | if params[:title].present? 15 | params[:title].split(' ').each do |title| 16 | @documents = @documents.search_title title 17 | end 18 | end 19 | 20 | if params[:keyword].present? 21 | params[:keyword].split(' ').each do |keyword| 22 | @documents = @documents.search_markdown keyword 23 | end 24 | end 25 | 26 | @documents = @documents.order(updated_at: :desc).page(params[:page]).per(10) 27 | end 28 | 29 | def show 30 | end 31 | 32 | def new 33 | @document = Document.new 34 | @templates = Template.order(:id).each do |template| 35 | template.replace_title current_user 36 | end 37 | end 38 | 39 | def create 40 | @document = Document.new document_params 41 | @result = @document.save 42 | 43 | if @result 44 | @document.user_documents.create user_id: current_user.id 45 | if @document.is_draft? 46 | flash[:notice] = 'ドキュメントを下書きしました。' 47 | else 48 | WebHookJob.perform_later current_user.id, @document.id, 'create' 49 | @document.create_markdown 50 | flash[:notice] = 'ドキュメントを公開しました。' 51 | end 52 | end 53 | 54 | render :submit 55 | end 56 | 57 | def edit 58 | @templates = Template.order(:id).each do |template| 59 | template.replace_title current_user 60 | end 61 | end 62 | 63 | def update 64 | old_title = @document.title 65 | was_draft = @document.is_draft? 66 | @result = @document.update document_params 67 | 68 | if @result 69 | unless @document.users.id_is(current_user.id) 70 | @document.user_documents.create user_id: current_user.id 71 | end 72 | 73 | if was_draft && @document.is_publish? 74 | WebHookJob.perform_later current_user.id, @document.id, 'create' 75 | @document.create_markdown 76 | elsif @document.is_publish? 77 | WebHookJob.perform_later current_user.id, @document.id, 'update' 78 | @document.update_markdown old_title 79 | end 80 | 81 | flash[:notice] = 'ドキュメントを更新しました。' 82 | end 83 | 84 | render :submit 85 | end 86 | 87 | def delete 88 | end 89 | 90 | def destroy 91 | @document.destroy_markdown 92 | @result = @document.destroy 93 | 94 | if @result 95 | flash[:notice] = 'ドキュメントを削除しました。' 96 | else 97 | flash[:alert] = 'ドキュメントを削除できませんでした。' 98 | end 99 | 100 | redirect_to documents_path 101 | end 102 | 103 | private 104 | 105 | def load_document 106 | @document = Document.id_is(params[:id]) if params[:id] 107 | end 108 | 109 | def document_params 110 | params.require(:document).permit :title, :markdown, :draft_flag 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /app/controllers/pictures_controller.rb: -------------------------------------------------------------------------------- 1 | class PicturesController < ApplicationController 2 | before_action :authenticate_user! 3 | 4 | def create 5 | params[:files].each do |file| 6 | picture = Picture.new attachment: file 7 | 8 | if picture.save 9 | if picture.attachment_content_type == 'application/pdf' 10 | data = { 11 | image: picture.pdf_url, 12 | url: picture.attachment.url, 13 | file_name: picture.attachment_file_name 14 | } 15 | else 16 | data = { 17 | image: picture.attachment.url, 18 | url: picture.attachment.url, 19 | file_name: picture.attachment_file_name 20 | } 21 | end 22 | WebsocketRails[current_user.account].trigger :create_picture, data 23 | end 24 | end 25 | 26 | render nothing: true 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /app/controllers/record_controller.rb: -------------------------------------------------------------------------------- 1 | class RecordController < ApplicationController 2 | before_action :authenticate_user! 3 | 4 | def index 5 | @templates = Template.where.not(pattern: '') 6 | return unless params[:template].present? && params[:date].present? 7 | template = Template.id_is(params[:template]) 8 | 9 | date = Date.strptime(params[:date], '%y / %m / %d') 10 | date_str = date.strftime('%y%m%d') 11 | documents = Document.publish.search_title(template.name).search_title(date_str).includes(:users).order('users.grade desc', 'users.account asc') 12 | 13 | attends = {} 14 | outline_str = '' 15 | date_str = date.strftime("%Y.%m.%d(#{%w(日 月 火 水 木 金 土)[date.wday]})") 16 | 17 | documents.each do |document| 18 | user = document.users.last 19 | family_name = user.name.split(' ').first 20 | 21 | attends[user.grade] = [] unless attends[user.grade] 22 | attends[user.grade] << family_name 23 | 24 | matches = document.markdown.match(/#{template.pattern}/) 25 | outline_str += "○ #{family_name}\n\n" 26 | if matches 27 | outline_str += "#{matches[1]}\n\n" 28 | end 29 | end 30 | 31 | attend_str = '' 32 | attends.each do |grade, names| 33 | attend_str += "○ #{Grade::TEXT[grade]} #{names.join('、')}\n" 34 | end 35 | 36 | @record = "□ #{template.name}議事録 #{date_str}\n\n● 出席\n\n#{attend_str}\n● #{template.name}\n\n#{outline_str}".chomp 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /app/controllers/templates_controller.rb: -------------------------------------------------------------------------------- 1 | class TemplatesController < ApplicationController 2 | before_action :authenticate_user! 3 | before_action :load_template 4 | 5 | def index 6 | @templates = Template.order(updated_at: :desc).page(params[:page]).per(10) 7 | end 8 | 9 | def show 10 | end 11 | 12 | def new 13 | @template = Template.new 14 | end 15 | 16 | def create 17 | @template = Template.new template_params 18 | @result = @template.save 19 | flash[:notice] = 'テンプレートを作成しました。' if @result 20 | render :submit 21 | end 22 | 23 | def edit 24 | end 25 | 26 | def update 27 | @result = @template.update template_params 28 | flash[:notice] = 'テンプレートを更新しました。' if @result 29 | render :submit 30 | end 31 | 32 | def delete 33 | end 34 | 35 | def destroy 36 | @result = @template.destroy 37 | 38 | if @result 39 | flash[:notice] = 'テンプレートを削除しました。' 40 | else 41 | flash[:alert] = 'テンプレートを削除できませんでした。' 42 | end 43 | 44 | redirect_to templates_path 45 | end 46 | 47 | def select 48 | @template.replace_title current_user 49 | end 50 | 51 | private 52 | 53 | def load_template 54 | @template = Template.id_is(params[:id]) if params[:id] 55 | end 56 | 57 | def template_params 58 | params.require(:template).permit :name, :title, :markdown, :pattern 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /app/controllers/top_controller.rb: -------------------------------------------------------------------------------- 1 | class TopController < ApplicationController 2 | def index 3 | redirect_to documents_path if user_signed_in? 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/devise_helper.rb: -------------------------------------------------------------------------------- 1 | module DeviseHelper 2 | def devise_error_messages! 3 | return '' if resource.errors.empty? 4 | 5 | messages = resource.errors.full_messages.map { |msg| content_tag( :li, msg ) }.join 6 | sentence = I18n.t( 7 | 'errors.messages.not_saved', 8 | count: resource.errors.count, 9 | resource: resource.class.model_name.human.downcase 10 | ) 11 | 12 | html = sentence 13 | html.html_safe 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/jobs/file_job.rb: -------------------------------------------------------------------------------- 1 | class FileJob < ActiveJob::Base 2 | queue_as :file 3 | 4 | SAVE_DIR = "#{Rails.root}/public/documents" 5 | 6 | def perform(id, old_title) 7 | if old_title 8 | File.delete "#{SAVE_DIR}/#{old_title}.md" 9 | delete_dir_p old_title 10 | end 11 | 12 | if id 13 | document = Document.id_is id 14 | dir_path = get_dir_path document.title 15 | file_name = document.title.split('/').last 16 | 17 | FileUtils.mkdir_p dir_path 18 | write_file "#{dir_path}/#{file_name}.md", document.markdown 19 | end 20 | end 21 | 22 | def get_dir_path(title) 23 | dir = title.scan(/(.+)\/.+$/).flatten.first 24 | 25 | if dir 26 | return "#{SAVE_DIR}/#{dir}" 27 | else 28 | return SAVE_DIR 29 | end 30 | end 31 | 32 | def write_file(file_path, markdown) 33 | File.open(file_path, 'w') do |f| 34 | f.print markdown 35 | end 36 | end 37 | 38 | def delete_dir_p(old_title) 39 | dirs = old_title.split('/') 40 | dirs.pop 41 | 42 | while dirs.size > 0 43 | dir = "#{SAVE_DIR}/#{dirs.join '/'}" 44 | if Dir.entries(dir).join == '...' 45 | Dir.rmdir dir 46 | dirs.pop 47 | else 48 | break 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /app/jobs/web_hook_job.rb: -------------------------------------------------------------------------------- 1 | class WebHookJob < ActiveJob::Base 2 | queue_as :web_hook 3 | 4 | def perform(user_id, document_id, action) 5 | user = User.id_is user_id 6 | document = Document.id_is document_id 7 | routes = Rails.application.routes.url_helpers 8 | action = { 9 | 'create' => '作成', 10 | 'update' => '更新' 11 | }[action] 12 | 13 | attachment = {} 14 | attachment[:fallback] = "#{user.name.split(' ').first}さんが「#{document.title}」を#{action}しました。" 15 | attachment[:title] = attachment[:fallback] 16 | attachment[:title_link] = routes.document_url document_id, host: `hostname -f`.chomp 17 | attachment[:text] = document.markdown.gsub(/!\[.+\]\(.+\)/, '').gsub(/\[(.+)\]\((.+)\)/, '<$2|$1>') 18 | attachment[:color] = '#9c9990' 19 | attachment[:mrkdwn_in] = ['text'] 20 | 21 | images = document.markdown.match(/!\[.+\]\((.+)\)/) 22 | attachment[:image_url] = images[1] if images 23 | 24 | payload = {} 25 | payload[:username] = '書庫' 26 | payload[:icon_emoji] = ':memo:' 27 | payload[:attachments] = [attachment] 28 | 29 | payload = payload.to_json 30 | 31 | WebHook.all.each do |web_hook| 32 | uri = URI.parse web_hook.url 33 | http = Net::HTTP.new uri.host, uri.port 34 | http.use_ssl = true if web_hook.url.include? 'https' 35 | 36 | request = Net::HTTP::Post.new uri.request_uri 37 | request['Content-Type'] = 'application/json' 38 | request.body = payload 39 | 40 | http.request request 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sai-lab/shoko/bbe01346c725ee7342956c57f2295ce1e44636d6/app/mailers/.keep -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sai-lab/shoko/bbe01346c725ee7342956c57f2295ce1e44636d6/app/models/.keep -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sai-lab/shoko/bbe01346c725ee7342956c57f2295ce1e44636d6/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/concerns/grade.rb: -------------------------------------------------------------------------------- 1 | module Grade 2 | TEXT = %w(TR B1 B2 B3 B4 M1 M2 D1 D2 D3) 3 | SELECT = [ 4 | ['TR', 0], 5 | ['B1', 1], ['B2', 2], ['B3', 3], ['B4', 4], 6 | ['M1', 5], ['M2', 6], 7 | ['D1', 7], ['D2', 8], ['D3', 9] 8 | ] 9 | 10 | def self.included(base) 11 | base.class_eval do 12 | validates :grade, inclusion: { in: 0..9 } 13 | 14 | public 15 | 16 | def grade_text 17 | TEXT[self.grade] 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/models/document.rb: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: documents 4 | # 5 | # id :integer not null, primary key 6 | # title :string default(""), not null 7 | # markdown :text default(""), not null 8 | # draft_flag :boolean default(FALSE), not null 9 | # created_at :datetime not null 10 | # updated_at :datetime not null 11 | # 12 | 13 | class Document < ActiveRecord::Base 14 | validates_presence_of :title, :markdown 15 | 16 | has_many :user_documents, dependent: :destroy 17 | has_many :users, through: :user_documents 18 | 19 | scope :draft, -> { where(draft_flag: true) } 20 | scope :publish, -> { where(draft_flag: false) } 21 | scope :search_title, ->(keyword) { keyword ? Document.where(['title LIKE ?', "%#{PGconn.escape(keyword)}%"]) : Document.all } 22 | scope :search_markdown, ->(keyword) { keyword ? Document.where(['markdown LIKE ?', "%#{PGconn.escape(keyword)}%"]) : Document.all } 23 | 24 | def self.id_is(id) 25 | find_by(id: id.to_i) 26 | end 27 | 28 | def create_markdown 29 | FileJob.perform_later id, nil 30 | end 31 | 32 | def update_markdown(old_title) 33 | FileJob.perform_later id, old_title 34 | end 35 | 36 | def destroy_markdown 37 | FileJob.perform_later nil, title 38 | end 39 | 40 | def is_draft? 41 | draft_flag 42 | end 43 | 44 | def is_publish? 45 | !draft_flag 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /app/models/picture.rb: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: pictures 4 | # 5 | # id :integer not null, primary key 6 | # attachment_file_name :string 7 | # attachment_content_type :string 8 | # attachment_file_size :integer 9 | # attachment_updated_at :datetime 10 | # created_at :datetime not null 11 | # updated_at :datetime not null 12 | # 13 | 14 | class Picture < ActiveRecord::Base 15 | has_attached_file :attachment, 16 | url: '/pictures/:hash.:extension', 17 | path: "#{Rails.root}/public/pictures/:hash.:extension", 18 | hash_secret: 'longSecretString' 19 | 20 | validates_attachment :attachment, 21 | presence: true, 22 | content_type: { content_type: /(image|application)\/(jpeg|png|gif|pdf)/ } 23 | 24 | def self.id_is(id) 25 | find_by(id: id.to_i) 26 | end 27 | 28 | def pdf_url 29 | image_path = attachment.url.gsub('.pdf', '.png') 30 | absolute_image_path = attachment.path.gsub('.pdf', '.png') 31 | return image_path if File.exists?(absolute_image_path) 32 | pdf = Magick::ImageList.new(attachment.path + '[0]') 33 | cover_tmp = absolute_image_path 34 | pdf[0].write(cover_tmp) 35 | image_path 36 | end 37 | 38 | def destroy 39 | destroy_pdf_image 40 | super 41 | end 42 | 43 | def destroy_pdf_image 44 | return unless attachment_content_type == 'application/pdf' 45 | file_path = attachment.path.gsub('.pdf', '.png') 46 | File.delete(file_path) if File.exists?(file_path) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /app/models/template.rb: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: templates 4 | # 5 | # id :integer not null, primary key 6 | # title :string default(""), not null 7 | # markdown :text default(""), not null 8 | # created_at :datetime not null 9 | # updated_at :datetime not null 10 | # name :string default(""), not null 11 | # pattern :string default("") 12 | # 13 | 14 | class Template < ActiveRecord::Base 15 | validates_presence_of :name, :title, :markdown 16 | 17 | def self.id_is(id) 18 | find_by(id: id.to_i) 19 | end 20 | 21 | def replace_title(user) 22 | day = Time.now 23 | title.gsub! '%{year}', day.strftime('%y') 24 | title.gsub! '%{month}', day.strftime('%m') 25 | title.gsub! '%{day}', day.strftime('%d') 26 | title.gsub! '%{account}', user.account 27 | title.gsub! '%{name}', user.name 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: users 4 | # 5 | # id :integer not null, primary key 6 | # account :string default(""), not null 7 | # encrypted_password :string default(""), not null 8 | # name :string default(""), not null 9 | # created_at :datetime 10 | # updated_at :datetime 11 | # admin_flag :boolean default(FALSE), not null 12 | # grade :integer default(1), not null 13 | # email :string default(""), not null 14 | # reset_password_token :string 15 | # reset_password_sent_at :datetime 16 | # 17 | 18 | class User < ActiveRecord::Base 19 | devise :database_authenticatable, :registerable, :validatable, :recoverable 20 | validates_presence_of :name 21 | before_save :update_account! 22 | 23 | has_many :user_documents, dependent: :destroy 24 | has_many :documents, through: :user_documents 25 | 26 | include Grade 27 | 28 | def self.id_is(id) 29 | find_by(id: id.to_i) 30 | end 31 | 32 | def update_without_current_password(params, *options) 33 | params.delete(:current_password) 34 | params.delete(:password) if params[:password].blank? 35 | params.delete(:password_confirmation) if params[:password_confirmation].blank? 36 | 37 | clean_up_passwords 38 | update_attributes(params, *options) 39 | end 40 | 41 | def is_admin? 42 | admin_flag 43 | end 44 | 45 | private 46 | 47 | def update_account! 48 | self.account = email.match(/\A(.+)@/)[1] 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /app/models/user_document.rb: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: user_documents 4 | # 5 | # id :integer not null, primary key 6 | # user_id :integer not null 7 | # document_id :integer not null 8 | # created_at :datetime not null 9 | # updated_at :datetime not null 10 | # 11 | 12 | class UserDocument < ActiveRecord::Base 13 | belongs_to :user 14 | belongs_to :document 15 | end 16 | -------------------------------------------------------------------------------- /app/models/web_hook.rb: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: web_hooks 4 | # 5 | # id :integer not null, primary key 6 | # url :string default(""), not null 7 | # created_at :datetime not null 8 | # updated_at :datetime not null 9 | # name :string default(""), not null 10 | # 11 | 12 | class WebHook < ActiveRecord::Base 13 | validates_presence_of :name, :url 14 | 15 | def self.id_is(id) 16 | find_by(id: id.to_i) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/views/admin/documents/_list.html.slim: -------------------------------------------------------------------------------- 1 | - if documents.empty? 2 | .uk-alert.uk-alert-warning 3 | = fa_icon 'times', text: 'ドキュメントは存在しません。' 4 | 5 | - else 6 | .uk-overflow-container 7 | table.uk-table.uk-table-striped 8 | thead 9 | tr 10 | th style="width: 150px;" 11 | th.exo.exo-bold style="width: 300px;" ドキュメント 12 | th.exo.exo-bold style="width: 150px;" 最終更新日 13 | th.exo.exo-bold style="width: 50px;" 下書き 14 | th.exo.exo-bold Markdown 15 | tbody 16 | - documents.each do |document| 17 | tr 18 | td 19 | = link_to edit_document_path(document.id), class: 'uk-button uk-button-mini uk-button-success uk-margin-small-right' do 20 | = fa_icon 'pencil', text: '編集' 21 | = link_to delete_document_path(document.id), class: 'uk-button uk-button-mini uk-button-danger', remote: true do 22 | = fa_icon 'trash', text: '削除' 23 | td #{document.title} 24 | td #{I18n.l document.updated_at, format: :short} 25 | td.uk-text-center 26 | - if document.is_draft? 27 | = fa_icon 'check' 28 | td 29 | = link_to admin_document_path(document.id), remote: true do 30 | = fa_icon 'file-text-o', text: excerpt(document.markdown, '', radius: 25, omission: '…') 31 | -------------------------------------------------------------------------------- /app/views/admin/documents/_modal.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog.uk-modal-dialog-large 2 | a.uk-modal-close.uk-close 3 | #markdown 4 | 5 | javascript: 6 | markdown = '#{raw escape_javascript(document.markdown)}'; 7 | $('#markdown').html(marked(markdown, { breaks: true })); 8 | -------------------------------------------------------------------------------- /app/views/admin/documents/show.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/documents/modal", locals: { document: @document }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/pictures/_delete.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog 2 | a.uk-modal-close.uk-close 3 | 4 | .uk-modal-header 5 | h4.bold 6 | = fa_icon 'trash', text: '画像削除' 7 | 8 | | 「#{picture.attachment_file_name}」を削除しますか? 9 | 10 | .uk-modal-footer.uk-text-right 11 | .uk-button-group 12 | = link_to admin_picture_path, method: :delete, class: 'uk-button uk-button-danger' do 13 | = fa_icon 'trash', text: '削除' 14 | button.uk-button.uk-modal-close 15 | = fa_icon 'times', text: 'キャンセル' 16 | -------------------------------------------------------------------------------- /app/views/admin/pictures/_list.html.slim: -------------------------------------------------------------------------------- 1 | - if pictures.empty? 2 | .uk-alert.uk-alert-warning 3 | = fa_icon 'times', text: '画像は存在しません。' 4 | 5 | - else 6 | ul.uk-thumbnav.uk-grid-width-1-5 7 | - pictures.each do |picture| 8 | li 9 | - if picture.attachment_content_type == 'application/pdf' 10 | = link_to picture.attachment.url, target: :_blank 11 | .uk-thumbnail 12 | img src="#{picture.pdf_url}" alt="#{picture.attachment_file_name}" 13 | .uk-thumbnail-caption 14 | = link_to delete_admin_picture_path(picture.id), class: 'uk-button uk-button-danger uk-button-mini', remote: true 15 | = fa_icon 'trash', text: '削除' 16 | - else 17 | = link_to admin_picture_path(picture.id), remote: true do 18 | .uk-thumbnail 19 | img src="#{picture.attachment.url}" alt="#{picture.attachment_file_name}" 20 | .uk-thumbnail-caption 21 | = link_to delete_admin_picture_path(picture.id), class: 'uk-button uk-button-danger uk-button-mini', remote: true 22 | = fa_icon 'trash', text: '削除' 23 | -------------------------------------------------------------------------------- /app/views/admin/pictures/_modal.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog.uk-modal-dialog-large 2 | a.uk-modal-close.uk-close 3 | 4 | .uk-modal-header 5 | span.uk-h4.bold 6 | = fa_icon 'photo', text: picture.attachment_file_name 7 | span.uk-h6.uk-text-muted.uk-margin-small-left 8 | | (#{picture.attachment_content_type}) 9 | 10 | .uk-text-center 11 | img src="#{picture.attachment.url}" alt="#{picture.attachment_file_name}" 12 | 13 | .uk-modal-footer.uk-text-right 14 | button.uk-button.uk-modal-close 15 | = fa_icon 'times', text: '閉じる' 16 | -------------------------------------------------------------------------------- /app/views/admin/pictures/delete.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/pictures/delete", locals: { picture: @picture }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/pictures/index.html.slim: -------------------------------------------------------------------------------- 1 | - @title = '画像' 2 | 3 | h2.bold 4 | = fa_stacked_icon 'photo inverse', base: 'square', text: @title 5 | 6 | = render partial: 'admin/pictures/list', locals: { pictures: @pictures } 7 | = paginate @pictures 8 | 9 | coffee: 10 | $('#nav-admin').addClass('uk-active') 11 | -------------------------------------------------------------------------------- /app/views/admin/pictures/show.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/pictures/modal", locals: { picture: @picture }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/sidekiq/index.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'Sidekiq' 2 | 3 | h2.bold 4 | = fa_stacked_icon 'child inverse', base: 'square', text: @title 5 | 6 | iframe.uk-panel.uk-panel-box src="/sidekiq" 7 | 8 | coffee: 9 | $('#nav-admin').addClass('uk-active') 10 | -------------------------------------------------------------------------------- /app/views/admin/users/_delete.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog 2 | a.uk-modal-close.uk-close 3 | 4 | .uk-modal-header 5 | h4.bold 6 | = fa_icon 'trash', text: 'ユーザー削除' 7 | 8 | | 「#{user.account} (#{user.name})」を削除しますか? 9 | 10 | .uk-modal-footer.uk-text-right 11 | .uk-button-group 12 | = link_to admin_user_path, method: :delete, class: 'uk-button uk-button-danger' do 13 | = fa_icon 'trash', text: '削除' 14 | button.uk-button.uk-modal-close 15 | = fa_icon 'times', text: 'キャンセル' 16 | -------------------------------------------------------------------------------- /app/views/admin/users/_form.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog style="padding-bottom: 0" 2 | a.uk-modal-close.uk-close 3 | 4 | = form_for [:admin, user], html: { class: 'uk-form uk-form-stacked' }, remote: true do |f| 5 | .uk-modal-header 6 | h4.bold 7 | = fa_icon 'user', text: title 8 | 9 | .uk-form-row 10 | .uk-form-icon 11 | i.uk-icon-envelope 12 | = f.text_field :email, autofocus: true, placeholder: 'メールアドレス', style: 'padding-left: 30px;' 13 | .uk-form-help-block#user-email-error 14 | .uk-form-row 15 | .uk-form-icon 16 | i.uk-icon-font 17 | = f.text_field :name, placeholder: '名前', style: 'padding-left: 30px;' 18 | .uk-form-help-block#user-name-error 19 | .uk-form-row 20 | = f.select :grade, Grade::SELECT, {}, { class: 'uk-width-1-1' } 21 | .uk-form-help-block#user-grade-error 22 | .uk-form-row 23 | .uk-form-icon 24 | i.uk-icon-key 25 | = f.password_field :password, autocomplete: 'off', placeholder: 'パスワード', style: 'padding-left: 30px;' 26 | .uk-form-help-block#user-password-error 27 | .uk-form-row 28 | .uk-form-icon 29 | i.uk-icon-key 30 | = f.password_field :password_confirmation, autocomplete: 'off', placeholder: 'パスワード (確認)', style: 'padding-left: 30px;' 31 | .uk-form-help-block#user-password-confirmation-error 32 | .uk-form-row 33 | = f.check_box :admin_flag, class: 'uk-margin-left' 34 | = f.label :admin_flag, '管理者', class: 'uk-margin-left' 35 | 36 | .uk-modal-footer.uk-text-right 37 | .uk-button-group 38 | button.uk-button.uk-button-primary 39 | = fa_icon 'floppy-o', text: '保存' 40 | button.uk-button.uk-modal-close 41 | = fa_icon 'times', text: 'キャンセル' 42 | -------------------------------------------------------------------------------- /app/views/admin/users/_list.html.slim: -------------------------------------------------------------------------------- 1 | .uk-overflow-container 2 | table.uk-table.uk-table-striped 3 | thead 4 | tr 5 | th style="width: 150px;" 6 | = link_to new_admin_user_path, class: 'uk-button uk-button-mini uk-button-primary', remote: true do 7 | = fa_icon 'plus', text: '作成' 8 | th.bold style="width: 300px;" メールアドレス 9 | th.bold style="width: 150px;" 名前 10 | th.bold style="width: 50px;" 学年 11 | th.bold style="width: 50px;" 管理者 12 | th.bold ドキュメント 13 | tbody 14 | - users.includes(:documents).each do |user| 15 | tr 16 | td 17 | = link_to edit_admin_user_path(user.id), class: 'uk-button uk-button-mini uk-button-success uk-margin-small-right', remote: true do 18 | = fa_icon 'pencil', text: '編集' 19 | = link_to delete_admin_user_path(user.id), class: 'uk-button uk-button-mini uk-button-danger', remote: true do 20 | = fa_icon 'trash', text: '削除' 21 | td #{user.email} 22 | td #{user.name} 23 | td #{user.grade_text} 24 | td.uk-text-center 25 | - if user.is_admin? 26 | = fa_icon 'check' 27 | td 28 | = link_to admin_user_path(user.id) do 29 | = fa_icon 'files-o', text: "#{user.documents.size} ドキュメント" 30 | -------------------------------------------------------------------------------- /app/views/admin/users/delete.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/users/delete", locals: { user: @user }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/users/edit.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/users/form", locals: { user: @user, title: @user.account }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/users/index.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'ユーザー' 2 | 3 | h2.bold 4 | = fa_stacked_icon 'users inverse', base: 'square', text: @title 5 | 6 | = render partial: 'admin/users/list', locals: { users: @users } 7 | = paginate @users 8 | 9 | coffee: 10 | $('#nav-admin').addClass('uk-active') 11 | -------------------------------------------------------------------------------- /app/views/admin/users/new.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/users/form", locals: { user: @user, title: "ユーザー作成"}) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/users/show.html.slim: -------------------------------------------------------------------------------- 1 | - @title = @user.account 2 | 3 | p 4 | span.uk-h2.bold 5 | = fa_stacked_icon 'user inverse', base: 'square', text: @title 6 | span.uk-h4.uk-text-muted.uk-margin-small-left 7 | | (#{@user.name}) 8 | 9 | = render partial: 'admin/documents/list', locals: { documents: @documents } 10 | = paginate @documents 11 | 12 | coffee: 13 | $('#nav-admin').addClass('uk-active') 14 | -------------------------------------------------------------------------------- /app/views/admin/users/submit.js.coffee: -------------------------------------------------------------------------------- 1 | <% if @user.errors.empty? %> 2 | location.reload(true) 3 | <% else %> 4 | $('[id^=user_]' ).removeClass('uk-form-danger') 5 | $('.uk-form-help-block').empty() 6 | <% if @user.errors.messages[:email] %> 7 | $('#user_email').addClass('uk-form-danger') 8 | $('#user-email-error').html('<%= escape_javascript(render partial: "error/form", locals: { label: "メールアドレス", messages: @user.errors.messages[:email] }) %>') 9 | <% end %> 10 | <% if @user.errors.messages[:name] %> 11 | $('#user_name').addClass('uk-form-danger') 12 | $('#user-name-error').html('<%= escape_javascript(render partial: "error/form", locals: { label: "名前", messages: @user.errors.messages[:name] }) %>') 13 | <% end %> 14 | <% if @user.errors.messages[:grade] %> 15 | $('#user_grade').addClass('uk-form-danger') 16 | $('#user-grade-error').html('<%= escape_javascript(render partial: "error/form", locals: { label: "学年", messages: @user.errors.messages[:grade] }) %>') 17 | <% end %> 18 | <% if @user.errors.messages[:password] %> 19 | $('#user_password').addClass('uk-form-danger') 20 | $('#user-password-error').html('<%= escape_javascript(render partial: "error/form", locals: { label: "パスワード", messages: @user.errors.messages[:password] }) %>') 21 | <% end %> 22 | <% if @user.errors.messages[:password_confirmation] %> 23 | $('#user_password_confirmation').addClass('uk-form-danger') 24 | $('#user-password-15~confirmation-error').html('<%= escape_javascript(render partial: "error/form", locals: { label: "確認のパスワード", messages: @user.errors.messages[:password_confirmation] }) %>') 25 | <% end %> 26 | <% end %> 27 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/_delete.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog 2 | a.uk-modal-close.uk-close 3 | 4 | .uk-modal-header 5 | h4.bold 6 | = fa_icon 'trash', text: 'WebHook削除' 7 | 8 | | 「#{web_hook.name}」を削除しますか? 9 | 10 | .uk-modal-footer.uk-text-right 11 | .uk-button-group 12 | = link_to admin_web_hook_path, method: :delete, class: 'uk-button uk-button-danger' do 13 | = fa_icon 'trash', text: '削除' 14 | button.uk-button.uk-modal-close 15 | = fa_icon 'times', text: 'キャンセル' 16 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/_form.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog style="padding-bottom: 0" 2 | a.uk-modal-close.uk-close 3 | 4 | = form_for [:admin, web_hook], html: { class: 'uk-form uk-form-stacked' }, remote: true do |f| 5 | .uk-modal-header 6 | h4.bold 7 | = fa_icon 'anchor', text: title 8 | 9 | .uk-form-row 10 | .uk-form-icon 11 | i.uk-icon-font 12 | = f.text_field :name, autofocus: true, placeholder: '名前', style: 'padding-left: 30px;' 13 | .uk-form-help-block#web_hook-name-error 14 | .uk-form-row 15 | .uk-form-icon 16 | i.uk-icon-link 17 | = f.text_field :url, placeholder: 'URL', style: 'padding-left: 30px;' 18 | .uk-form-help-block#web_hook-url-error 19 | 20 | .uk-modal-footer.uk-text-right 21 | .uk-button-group 22 | button.uk-button.uk-button-primary 23 | = fa_icon 'floppy-o', text: '保存' 24 | button.uk-button.uk-modal-close 25 | = fa_icon 'times', text: 'キャンセル' 26 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/_list.html.slim: -------------------------------------------------------------------------------- 1 | .uk-overflow-container 2 | table.uk-table.uk-table-striped 3 | thead 4 | tr 5 | th style="width: 150px;" 6 | = link_to new_admin_web_hook_path, class: 'uk-button uk-button-mini uk-button-primary', remote: true do 7 | = fa_icon 'plus', text: '作成' 8 | th.bold style="width: 150px;" 名前 9 | th.bold URL 10 | tbody 11 | - web_hooks.each do |web_hook| 12 | tr 13 | td 14 | = link_to edit_admin_web_hook_path(web_hook.id), class: 'uk-button uk-button-mini uk-button-success uk-margin-small-right', remote: true do 15 | = fa_icon 'pencil', text: '編集' 16 | = link_to delete_admin_web_hook_path(web_hook.id), class: 'uk-button uk-button-mini uk-button-danger', remote: true do 17 | = fa_icon 'trash', text: '削除' 18 | td #{web_hook.name} 19 | td #{web_hook.url} 20 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/delete.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/web_hooks/delete", locals: { web_hook: @web_hook }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/edit.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/web_hooks/form", locals: { web_hook: @web_hook, title: "WebHook編集" }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/index.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'WebHook' 2 | 3 | h2.bold 4 | = fa_stacked_icon 'slack inverse', base: 'square', text: @title 5 | 6 | = render partial: 'admin/web_hooks/list', locals: { web_hooks: @web_hooks } 7 | = paginate @web_hooks 8 | 9 | coffee: 10 | $('#nav-admin').addClass('uk-active') 11 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/new.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "admin/web_hooks/form", locals: { web_hook: @web_hook, title: "WebHook作成"}) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/admin/web_hooks/submit.js.coffee: -------------------------------------------------------------------------------- 1 | <% if @web_hook.errors.empty? %> 2 | location.reload(true) 3 | <% else %> 4 | $('[id^=web-hook_]' ).removeClass('uk-form-danger') 5 | $('.uk-form-help-block').empty() 6 | <% if @web_hook.errors.messages[:name] %> 7 | $('#web_hook_name').addClass('uk-form-danger') 8 | $('#web_hook-name-error').html('<%= escape_javascript(render partial: "error/form", locals: { label: "名前", messages: @web_hook.errors.messages[:name] }) %>') 9 | <% end %> 10 | <% if @web_hook.errors.messages[:url] %> 11 | $('#web_hook_url').addClass('uk-form-danger') 12 | $('#web_hook-url-error').html('<%= escape_javascript(render partial: "error/form", locals: { label: "URL", messages: @web_hook.errors.messages[:url] }) %>') 13 | <% end %> 14 | <% end %> 15 | -------------------------------------------------------------------------------- /app/views/devise/mailer/reset_password_instructions.html.slim: -------------------------------------------------------------------------------- 1 | p 2 | | #{@resource.name} さん、こんにちは。 3 | br 4 | | 書庫をご利用いただきありがとうございます。 5 | 6 | p 7 | | パスワードリセットのリクエストが行われました。 8 | br 9 | | 以下のリンクをクリックして、パスワードを変更できます。 10 | 11 | p 12 | | #{edit_password_url( @resource, reset_password_token: @token )} 13 | 14 | p 15 | | もしあなたがパスワードリセットをリクエストしていない場合は、このメールを無視して下さい。 16 | br 17 | | 上記リンクをクリックして新しいパスワードを作成しない限り、パスワードは変更されません。 18 | 19 | p 20 | | (c) #{Shoko::Application.config.copyright} 21 | br 22 | | #{root_url} 23 | -------------------------------------------------------------------------------- /app/views/devise/passwords/edit.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'パスワードのリセット' 2 | - password_error = resource.errors.messages[:password].present? 3 | - password_confirmation_error = resource.errors.messages[:password_confirmation].present? 4 | 5 | .uk-width-medium-1-2.uk-container-center 6 | .uk-panel.uk-panel-box 7 | .uk-panel-title.bold 8 | = fa_icon 'key', text: @title 9 | 10 | .uk-nav-side 11 | .uk-nav-divider 12 | 13 | = form_for resource, as: resource_name, html: { class: 'uk-form uk-form-stacked', method: :put }, url: password_path(resource_name) do |f| 14 | = f.hidden_field :reset_password_token 15 | .uk-form-row 16 | .uk-form-icon 17 | i.uk-icon-key class="#{'uk-text-danger' if password_error}" 18 | = f.password_field :password, autofocus: true, autocomplete: 'off', placeholder: '新しいパスワード', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if password_error}" 19 | - if password_error 20 | .uk-form-help-block 21 | = render partial: 'error/form', locals: { label: '新しいパスワード', messages: resource.errors.messages[:password] } 22 | .uk-form-row 23 | .uk-form-icon 24 | i.uk-icon-key class="#{'uk-text-danger' if password_confirmation_error}" 25 | = f.password_field :password_confirmation, autocomplete: 'off', placeholder: '新しいパスワード (確認)', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if password_confirmation_error}" 26 | - if password_confirmation_error 27 | .uk-form-help-block 28 | = render partial: 'error/form', locals: { label: '確認のパスワード', messages: resource.errors.messages[:password_confirmation] } 29 | .uk-form-row 30 | .uk-button-group 31 | button.uk-button.uk-button-primary type="submit" 32 | = fa_icon 'refresh', text: 'リセット' 33 | = link_to new_user_session_path, class: 'uk-button' do 34 | = fa_icon 'sign-in', text: 'ログイン' 35 | 36 | - unless devise_error_messages!.empty? 37 | javascript: 38 | UIkit.notify({ message: '#{devise_error_messages!}', timeout: 3000, status: 'danger' }); 39 | -------------------------------------------------------------------------------- /app/views/devise/passwords/new.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'パスワードを忘れたら' 2 | - email_error = resource.errors.messages[:email].present? 3 | 4 | - unless devise_error_messages!.empty? 5 | javascript: 6 | UIkit.notify({ message: '#{devise_error_messages!}', timeout: 3000, status: 'danger' }); 7 | 8 | .uk-width-medium-1-2.uk-container-center 9 | .uk-panel.uk-panel-box 10 | .uk-panel-title.bold 11 | = fa_icon 'key', text: @title 12 | 13 | .uk-nav-side 14 | .uk-nav-divider 15 | 16 | = form_for resource, as: resource_name, html: { class: 'uk-form uk-form-stacked', method: :post }, url: password_path(resource_name) do |f| 17 | .uk-form-row 18 | .uk-form-icon 19 | i.uk-icon-envelope class="#{'uk-text-danger' if email_error}" 20 | = f.text_field :email, autofocus: true, placeholder: 'メールアドレス', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if email_error}" 21 | .uk-form-help-block 22 | ul.uk-text-warning.fa-ul 23 | li = fa_icon 'li exclamation-triangle', text: 'パスワードの再設定に必要な情報を送信します。' 24 | - if email_error 25 | = render partial: 'error/form', locals: { label: 'メールアドレス', messages: resource.errors.messages[:email] } 26 | .uk-form-row 27 | .uk-button-group 28 | button.uk-button.uk-button-primary type="submit" 29 | = fa_icon 'paper-plane', text: '送信' 30 | = link_to new_user_session_path, class: 'uk-button' do 31 | = fa_icon 'sign-in', text: 'ログイン' 32 | -------------------------------------------------------------------------------- /app/views/devise/registrations/edit.html.slim: -------------------------------------------------------------------------------- 1 | - @title = '編集' 2 | - email_error = resource.errors.messages[:email].present? 3 | - name_error = resource.errors.messages[:name].present? 4 | - current_password_error = resource.errors.messages[:current_password].present? 5 | - password_error = resource.errors.messages[:password].present? 6 | - password_confirmation_error = resource.errors.messages[:password_confirmation].present? 7 | 8 | .uk-width-medium-1-2.uk-container-center 9 | .uk-panel.uk-panel-box 10 | .uk-panel-title.bold 11 | = fa_icon 'pencil', text: @title 12 | 13 | .uk-nav-side 14 | .uk-nav-divider 15 | 16 | = form_for resource, as: resource_name, html: { class: 'uk-form uk-form-stacked' }, url: registration_path(resource_name) do |f| 17 | .uk-form-row 18 | .uk-form-icon 19 | i.uk-icon-envelope class="#{'uk-text-danger' if email_error}" 20 | = f.text_field :email, autofocus: true, placeholder: 'メールアドレス', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if email_error}" 21 | - if email_error 22 | .uk-form-help-block 23 | = render partial: 'error/form', locals: { label: 'メールアドレス', messages: resource.errors.messages[:email] } 24 | .uk-form-row 25 | .uk-form-icon 26 | i.uk-icon-user class="#{'uk-text-danger' if name_error}" 27 | = f.text_field :name, autofocus: true, placeholder: '名前', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if name_error}" 28 | - if name_error 29 | .uk-form-help-block 30 | = render partial: 'error/form', locals: { label: '名前', messages: resource.errors.messages[:name] } 31 | .uk-form-row 32 | .uk-form-icon 33 | i.uk-icon-key class="#{'uk-text-danger' if current_password_error}" 34 | = f.password_field :current_password, autocomplete: 'off', placeholder: '現在のパスワード', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if current_password_error}" 35 | - if current_password_error 36 | .uk-form-help-block 37 | = render partial: 'error/form', locals: { label: '現在のパスワード', messages: resource.errors.messages[:current_password] } 38 | .uk-form-row 39 | .uk-form-icon 40 | i.uk-icon-key class="#{'uk-text-danger' if password_error}" 41 | = f.password_field :password, autofocus: true, autocomplete: 'off', placeholder: '新しいパスワード', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if password_error}" 42 | - if password_error 43 | .uk-form-help-block 44 | = render partial: 'error/form', locals: { label: '新しいパスワード', messages: resource.errors.messages[:password] } 45 | .uk-form-row 46 | .uk-form-icon 47 | i.uk-icon-key class="#{'uk-text-danger' if password_confirmation_error}" 48 | = f.password_field :password_confirmation, autocomplete: 'off', placeholder: '新しいパスワード (確認)', style: 'padding-left: 30px;', class: "#{'uk-form-danger' if password_confirmation_error}" 49 | - if password_confirmation_error 50 | .uk-form-help-block 51 | = render partial: 'error/form', locals: { label: '確認のパスワード', messages: resource.errors.messages[:password_confirmation] } 52 | .uk-form-row 53 | button.uk-button.uk-button-primary type="submit" 54 | = fa_icon 'floppy-o', text: '更新' 55 | 56 | - unless devise_error_messages!.empty? 57 | javascript: 58 | UIkit.notify({ message: '#{devise_error_messages!}', timeout: 3000, status: 'danger' }); 59 | 60 | coffee: 61 | $('#nav-user').addClass('uk-active') 62 | -------------------------------------------------------------------------------- /app/views/devise/sessions/new.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'ログイン' 2 | 3 | .uk-width-medium-1-2.uk-container-center 4 | .uk-panel.uk-panel-box 5 | .uk-panel-title.bold 6 | = fa_icon 'sign-in', text: @title 7 | 8 | .uk-nav-side 9 | .uk-nav-divider 10 | 11 | = form_for resource, as: resource_name, html: { class: 'uk-form uk-form-stacked' }, url: session_path(resource_name) do |f| 12 | .uk-form-row.uk-form-icon 13 | i.uk-icon-user 14 | = f.text_field :account, autofocus: true, placeholder: 'アカウント名' 15 | .uk-form-row.uk-form-icon 16 | i.uk-icon-key 17 | = f.password_field :password, autocomplete: 'off', placeholder: 'パスワード' 18 | .uk-form-row 19 | .uk-button-group 20 | button.uk-button.uk-button-primary type="submit" 21 | = fa_icon 'sign-in', text: 'ログイン' 22 | = link_to new_password_path(:user), class: 'uk-button' do 23 | = fa_icon 'key', text: 'パスワードを忘れたら' 24 | -------------------------------------------------------------------------------- /app/views/documents/_delete.html.slim: -------------------------------------------------------------------------------- 1 | .uk-modal-dialog 2 | a.uk-modal-close.uk-close 3 | 4 | .uk-modal-header 5 | h4.bold 6 | = fa_icon 'trash', text: 'ドキュメント削除' 7 | 8 | | 「#{document.title}」を削除しますか? 9 | 10 | .uk-modal-footer.uk-text-right 11 | .uk-button-group 12 | = link_to document_path, method: :delete, class: 'uk-button uk-button-danger' do 13 | = fa_icon 'trash', text: '削除' 14 | button.uk-button.uk-modal-close 15 | = fa_icon 'times', text: 'キャンセル' 16 | -------------------------------------------------------------------------------- /app/views/documents/_dropdown.html.slim: -------------------------------------------------------------------------------- 1 | .uk-button-dropdown data-uk-dropdown="{ mode: 'click' }" 2 | button.uk-button.uk-button-large.uk-button-primary 3 | = fa_icon 'search' 4 | 5 | .uk-dropdown 6 | = form_tag documents_path, method: :get, class: 'uk-form uk-form-stacked' do 7 | .uk-form-row 8 | = select_tag :user, options_from_collection_for_select(users, :id, :name), { prompt: 'ユーザー', class: 'uk-width-1-1' } 9 | .uk-form-row 10 | .uk-form-icon 11 | i.uk-icon-font 12 | = text_field_tag :title, params[:title], placeholder: 'タイトル' 13 | .uk-form-row 14 | .uk-form-icon 15 | i.uk-icon-paragraph 16 | = text_field_tag :keyword, params[:keyword], placeholder: 'キーワード' 17 | 18 | .uk-nav-side 19 | .uk-nav-divider 20 | 21 | .uk-form-row 22 | button.uk-button.uk-button-primary onClick="$('.uk-dropdown > .uk-form').submit()" 23 | = fa_icon 'search', text: '検索' 24 | -------------------------------------------------------------------------------- /app/views/documents/_list.html.slim: -------------------------------------------------------------------------------- 1 | - if documents.empty? 2 | .uk-alert.uk-alert-warning 3 | = fa_icon 'times', text: 'ドキュメントは存在しません。' 4 | 5 | - else 6 | dl.uk-description-list-line 7 | - documents.includes(:users).each do |document| 8 | dt 9 | = link_to document.title, document_path(document.id), class: 'uk-h3 uk-margin-right' 10 | - if document.is_draft? 11 | span.uk-text-muted.uk-margin-small-right data-uk-tooltip="" title="下書き" 12 | = fa_icon 'file' 13 | = link_to edit_document_path(document.id) do 14 | span.uk-text-success data-uk-tooltip="" title="編集" 15 | = fa_icon 'pencil' 16 | = link_to delete_document_path(document.id), remote: true do 17 | span.uk-text-danger.uk-margin-small-left data-uk-tooltip="" title="削除" 18 | = fa_icon 'trash' 19 | 20 | dd 21 | = fa_icon 'users' 22 | span.uk-margin-small-left #{document.users.pluck(:name).join(', ')} 23 | span.uk-margin-left 24 | = fa_icon 'calendar' 25 | span.uk-margin-small-left #{I18n.l document.updated_at, format: :short} 26 | 27 | - if params[:keyword].present? 28 | - keywords = params[:keyword].split ' ' 29 | dd 30 | = highlight excerpt(document.markdown, keywords.first, radius: 30, omission: ''), keywords 31 | -------------------------------------------------------------------------------- /app/views/documents/_sidebar.html.slim: -------------------------------------------------------------------------------- 1 | .uk-panel.uk-panel-box 2 | = form_tag documents_path, method: :get, class: 'uk-form uk-form-stacked' do 3 | .uk-panel-title.bold 4 | = fa_icon 'search', text: '検索' 5 | 6 | .uk-nav-side 7 | .uk-nav-divider 8 | 9 | .uk-form-row 10 | = select_tag :user, options_from_collection_for_select(users, :id, :name), { prompt: 'ユーザー', class: 'uk-width-1-1' } 11 | .uk-form-row 12 | .uk-form-icon 13 | i.uk-icon-font 14 | = text_field_tag :title, params[:title], placeholder: 'タイトル' 15 | .uk-form-row 16 | .uk-form-icon 17 | i.uk-icon-paragraph 18 | = text_field_tag :keyword, params[:keyword], placeholder: 'キーワード' 19 | 20 | .uk-nav-side 21 | .uk-nav-divider 22 | 23 | .uk-form-row 24 | button.uk-button.uk-button-primary onClick="$('.uk-panel > .uk-form').submit()" 25 | = fa_icon 'search', text: '検索' 26 | -------------------------------------------------------------------------------- /app/views/documents/delete.js.coffee: -------------------------------------------------------------------------------- 1 | $('.uk-modal').html('<%= escape_javascript(render partial: "documents/delete", locals: { document: @document }) %>') 2 | UIkit.modal('.uk-modal').show() 3 | -------------------------------------------------------------------------------- /app/views/documents/edit.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'ドキュメント編集' 2 | 3 | h2.bold 4 | = fa_stacked_icon 'file-text inverse', base: 'square', text: @title 5 | 6 | = render partial: 'documents/form', locals: { document: @document, templates: @templates } 7 | 8 | coffee: 9 | $('#nav-documents').addClass('uk-active') 10 | -------------------------------------------------------------------------------- /app/views/documents/index.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'ドキュメント' 2 | 3 | .relative 4 | h2.bold 5 | = fa_stacked_icon 'file-text inverse', base: 'square', text: @title 6 | .absolute-top.absolute-right.uk-visible-small 7 | = render partial: 'documents/dropdown', locals: { users: @users } 8 | 9 | .uk-grid 10 | .uk-width-medium-3-10 11 | .uk-hidden-small 12 | = render partial: 'documents/sidebar', locals: { users: @users } 13 | .uk-width-medium-7-10 14 | = render partial: 'documents/list', locals: { documents: @documents } 15 | = paginate @documents 16 | 17 | javascript: 18 | user = '#{params[:user]}' 19 | 20 | coffee: 21 | $('#nav-documents').addClass('uk-active') 22 | $('select#user').val(user) 23 | $('select#user').on 'change', -> 24 | if $(this).val() == '' 25 | $(this).addClass('placeholder') 26 | else 27 | $(this).removeClass('placeholder') 28 | $('select#user').change() 29 | -------------------------------------------------------------------------------- /app/views/documents/new.html.slim: -------------------------------------------------------------------------------- 1 | - @title = 'ドキュメント作成' 2 | 3 | h2.bold 4 | = fa_stacked_icon 'file-text inverse', base: 'square', text: @title 5 | 6 | = render partial: 'documents/form', locals: { document: @document, templates: @templates } 7 | 8 | coffee: 9 | $('#nav-documents').addClass('uk-active') 10 | -------------------------------------------------------------------------------- /app/views/documents/show.html.slim: -------------------------------------------------------------------------------- 1 | - @title = @document.title 2 | 3 | article.uk-article 4 | dd.uk-text-muted 5 | span.uk-article-title.uk-margin-right #{@document.title} 6 | - if @document.is_draft? 7 | span.uk-text-muted.uk-margin-small-right data-uk-tooltip="" title="下書き" 8 | = fa_icon 'file' 9 | = link_to edit_document_path do 10 | span.uk-text-success data-uk-tooltip="" title="編集" 11 | = fa_icon 'pencil' 12 | = link_to delete_document_path, remote: true do 13 | span.uk-text-danger.uk-margin-small-left data-uk-tooltip="" title="削除" 14 | = fa_icon 'trash' 15 | 16 | p 17 | = fa_icon 'users' 18 | span.uk-margin-small-left #{@document.users.pluck(:name).join(', ')} 19 | span.uk-margin-left 20 | = fa_icon 'calendar' 21 | span.uk-margin-small-left #{I18n.l @document.updated_at, format: :short} 22 | 23 | hr.uk-article-divider 24 | 25 | .markdown-body 26 | 27 | javascript: 28 | markdown = '#{raw escape_javascript(@document.markdown)}'; 29 | 30 | coffee: 31 | $('#nav-documents').addClass('uk-active') 32 | marked.setOptions { 33 | breaks: true 34 | gfm: true 35 | highlight: (code) -> 36 | return hljs.highlightAuto(code).value 37 | } 38 | $('.markdown-body').html marked(markdown) 39 | -------------------------------------------------------------------------------- /app/views/documents/submit.js.coffee: -------------------------------------------------------------------------------- 1 | <% if @result %> 2 | location.href = '/documents/<%= @document.id %>' 3 | <% else %> 4 | UIkit.notify({ message: 'タイトルと本文を入力してください。', timeout: 3000, status : 'danger' }) 5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/error/_form.html.slim: -------------------------------------------------------------------------------- 1 | ul.uk-text-danger.fa-ul 2 | - messages.each do |message| 3 | li = fa_icon 'li times-circle', text: "#{label}#{message}" 4 | -------------------------------------------------------------------------------- /app/views/kaminari/_first_page.html.erb: -------------------------------------------------------------------------------- 1 | <% if current_page.first? %> 2 |
47 | ご指定のページは削除されたか、移動した可能性がございます。 48 |
49 | 50 | トップに戻る 51 | 52 |
47 | ご不便をおかけし申し訳ございません。
48 |
49 | 正常にご覧いただけるよう、解決に取り組んでおります。
50 |
47 | ご不便をおかけし申し訳ございません。
48 |
49 | 正常にご覧いただけるよう、解決に取り組んでおります。
50 |