Skip to content

Feature/custom pages #820

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions app/assets/javascripts/rails_admin/custom/parse_markdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$(document).on('rails_admin.dom_ready', function() {
if($('.markdown-input').length && $('.markdown-output').length) {
const input = $('.markdown-input')[0]
const output = $('.markdown-output')[0]
output.innerHTML = marked.parse(input.value)
input.addEventListener('input', function(a,b) {
output.innerHTML = marked.parse(input.value)
})
}
});

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions app/assets/stylesheets/pages.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Place all the styles related to the Pages controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
13 changes: 13 additions & 0 deletions app/controllers/pages_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

class PagesController < ApplicationController
before_action :load_game

def index
@pages = @game.pages
end

def show
@page = @game.pages.find_by path: params[:id].downcase
end
end
4 changes: 4 additions & 0 deletions app/helpers/pages_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

module PagesHelper
end
1 change: 1 addition & 0 deletions app/models/game.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Game < ApplicationRecord
has_many :standard_solved_challenges, through: :divisions
has_many :pentest_solved_challenges, through: :divisions
has_many :solved_challenges, through: :divisions
has_many :pages
end

enum board_layout: { jeopardy: 0, teams_x_challenges: 1, multiple_categories: 2, title_and_description: 3 }
Expand Down
19 changes: 19 additions & 0 deletions app/models/page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class Page < ApplicationRecord
belongs_to :game, optional: false

validates :path,
presence: true,
uniqueness: { scope: :game_id, case_sensitive: false },
format: { with: /\A[a-zA-Z\-]*\z/, message: 'path can only consist of letters and dashes' }
before_save :downcase_path

def preview
body
end

def downcase_path
path.downcase!
end
end
8 changes: 8 additions & 0 deletions app/views/pages/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- content_for :header do
= t('pages.index.pages_header')
- if @pages.count == 0
%h4{ class: "zero-items-text" }= t('pages.no_pages')
- else
- @pages.each do |page|
%div.page
= link_to page.title, game_page_path(page.path)
12 changes: 12 additions & 0 deletions app/views/pages/show.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
- content_for :header do
%div{ :class => "title" }
- if @page.title.blank?
= t('pages.show.no_title')
- else
= @page.title

%div{ :class => "body", :style => "margin-bottom:40px;" }
- if @page.body.blank?
= t('pages.show.no_body')
- else
= sanitize(Kramdown::Document.new(@page.body, :input => 'markdown').to_html)
1 change: 1 addition & 0 deletions app/views/rails_admin/main/_markdown_input.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
%textarea{class: 'form-control markdown-input', rows: '10', cols: '64', name: 'page[body]', id: 'page_body'}=form.object.body
2 changes: 2 additions & 0 deletions app/views/rails_admin/main/_markdown_output.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
%div{class: 'markdown-output', style: 'width: fit-content; border: 1px solid #ccc; border-radius: 4px; padding: 6px 12px', readonly: true}=form.object.body
%p{class: 'markdown-disclaimer'}Disclaimer: Preview may appear differently on final page. Use two returns for line breaks.
5 changes: 5 additions & 0 deletions app/views/rails_admin/main/_page_url.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.input-group
.input-group-addon
%span{class: 'input-group-text'}=request.host + (request.local? ? ':3000' : '') + '/game/pages/'
%input.form-control{id: "page_path", name: 'page[path]', type: "text", value: form.object.path}

29 changes: 29 additions & 0 deletions config/initializers/rails_admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,35 @@
end
end

config.model 'Page' do
edit do
field :title
field :body do
partial "markdown_input"
end
field :preview do
partial "markdown_output"
end
field :path do
partial "page_url"
end
field :game
end
list do
field :title
field :path do
label 'Link'
pretty_value do
v = bindings[:view]
page = bindings[:object]
url = page.path
v.link_to(url, '/game/pages/' + url)
end
end
field :game
end
end

# If you want to track changes on your models:
# config.audit_with :history, 'User'

Expand Down
7 changes: 7 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,13 @@ en:
messages:
messages_header: Messages
no_messages: No Messages
pages:
index:
pages_header: Custom Pages
no_pages: No pages
show:
no_title: Page
no_body: This page is empty
home:
index:
description: Description
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
get :privacy_notice
get :summary
get :terms_of_service
resources :pages, only: %i[index show]
resources :messages, only: [:index]
resources :achievements, only: [:index]
resources :divisions, only: [:index]
Expand Down
10 changes: 10 additions & 0 deletions db/migrate/20220114214507_create_pages.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreatePages < ActiveRecord::Migration[6.1]
def change
create_table :pages do |t|
t.string :title
t.text :body

t.timestamps
end
end
end
5 changes: 5 additions & 0 deletions db/migrate/20220118150442_add_game_to_pages.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddGameToPages < ActiveRecord::Migration[6.1]
def change
add_reference :pages, :game, null: false, foreign_key: true
end
end
5 changes: 5 additions & 0 deletions db/migrate/20220118214259_add_path_to_pages.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddPathToPages < ActiveRecord::Migration[6.1]
def change
add_column :pages, :path, :string
end
end
5 changes: 5 additions & 0 deletions db/migrate/20220118214936_change_column_null.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class ChangeColumnNull < ActiveRecord::Migration[6.1]
def change
change_column_null :pages, :path, false
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddUniqueIndexToGameIdAndPath < ActiveRecord::Migration[6.1]
def change
add_index :pages, [:game_id, :path], unique: true
end
end
16 changes: 14 additions & 2 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2021_10_11_144501) do
ActiveRecord::Schema.define(version: 2022_01_18_221736) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -195,6 +195,17 @@
t.index ["reset_password_token"], name: "index_models_on_reset_password_token", unique: true
end

create_table "pages", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "game_id", null: false
t.string "path", null: false
t.index ["game_id", "path"], name: "index_pages_on_game_id_and_path", unique: true
t.index ["game_id"], name: "index_pages_on_game_id"
end

create_table "rails_admin_histories", id: :serial, force: :cascade do |t|
t.text "message"
t.string "username"
Expand Down Expand Up @@ -236,8 +247,8 @@
t.integer "division_id"
t.boolean "eligible", default: false
t.integer "slots_available", default: 0
t.boolean "looking_for_members", default: true, null: false
t.string "team_location", default: ""
t.boolean "looking_for_members", default: true, null: false
t.index "lower((team_name)::text)", name: "index_teams_on_team_name_unique", unique: true
t.index ["division_id"], name: "index_teams_on_division_id"
t.index ["team_captain_id"], name: "index_teams_on_team_captain_id"
Expand Down Expand Up @@ -331,6 +342,7 @@
add_foreign_key "file_submissions", "challenges"
add_foreign_key "file_submissions", "users"
add_foreign_key "flags", "teams"
add_foreign_key "pages", "games"
add_foreign_key "submitted_flags", "flags"
add_foreign_key "teams", "divisions"
end
13 changes: 13 additions & 0 deletions test/controllers/pages_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "test_helper"

class PagesControllerTest < ActionController::TestCase

def setup
create(:active_game)
end

test "should get index" do
get :index
assert_response :success
end
end
9 changes: 9 additions & 0 deletions test/factories/pages.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FactoryBot.define do
factory :page do
title { "test custom page" }
body { "this is the body" }
path { "page" }

game
end
end
42 changes: 42 additions & 0 deletions test/integration/pages_display_model_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'test_helper'

class PagesDisplayModesTest < ActionDispatch::IntegrationTest
include TeamsHelper
include Devise::Test::IntegrationHelpers

def setup
@game = create(:active_game)
end

test 'page list displays correctly when there are pages' do
page = create(:page, title: 'Example Title', body: 'Example Body', path: 'page')

get "/game/pages"
assert_select 'div[class=page]' do
assert_select 'a', /Example Title/
assert_select 'a', :href => /game\/pages\/page/
end
end

test 'no pages show when there are no pages' do
get "/game/pages"
assert_select 'h4[class=zero-items-text]', /No Pages/
end

test 'page displays contents correctly' do
page = create(:page, title: 'Example Title', body: 'Example Body', path: 'page')

get "/game/pages/page"
assert_select 'div[class=title]', /Example Title/
assert_select 'div[class=body]', /Example Body/
end

test 'template page displays when page has no contents' do
page = create(:page, title: nil, body: nil, path: 'page')

get "/game/pages/page"
assert_select 'div[class=title]', /Page/
assert_select 'div[class=body]', /This page is empty/
end

end
13 changes: 13 additions & 0 deletions test/models/page_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "test_helper"

class PageTest < ActiveSupport::TestCase
def setup
create(:active_game)
end

test 'page preview reflects body' do
page = create(:page, title: 'Example Title', body: 'Example Body', path: 'page')

assert_equal page.preview, 'Example Body'
end
end