├── log
└── .gitkeep
├── lib
├── tasks
│ ├── .gitkeep
│ └── scraping.rake
└── assets
│ └── .gitkeep
├── app
├── mailers
│ └── .gitkeep
├── models
│ ├── .gitkeep
│ ├── code.rb
│ ├── media_threadx.rb
│ ├── threadx_collaborator.rb
│ ├── taxonomy.rb
│ ├── threadx_taxonomy.rb
│ ├── taxonomy_option.rb
│ ├── coded_page.rb
│ ├── taxonomy_classification.rb
│ ├── area.rb
│ ├── highlighted_area.rb
│ ├── media.rb
│ ├── user.rb
│ └── image.rb
├── helpers
│ ├── home_helper.rb
│ ├── users_helper.rb
│ ├── coding_helper.rb
│ ├── images_helper.rb
│ ├── media_helper.rb
│ ├── application_helper.rb
│ └── thread_helper.rb
├── assets
│ ├── images
│ │ ├── 404.jpg
│ │ ├── rails.png
│ │ ├── favicon.ico
│ │ ├── icon-close.png
│ │ ├── icon-edit.png
│ │ ├── header-blog.png
│ │ ├── transparent.png
│ │ ├── twitter-icon.png
│ │ ├── youtube-icon.png
│ │ ├── header-blog-2.png
│ │ ├── wordpress-icon.png
│ │ ├── imago-pageonex-1.png
│ │ ├── imago-pageonex-2.png
│ │ ├── imago-pageonex-3.png
│ │ ├── imago-pageonex-4.png
│ │ └── detail-front-pages.png
│ ├── javascripts
│ │ ├── images
│ │ │ ├── colors.png
│ │ │ └── trigger.png
│ │ ├── bootstrap.js.coffee
│ │ ├── home.js.coffee
│ │ ├── threads.js.coffee
│ │ ├── utils.js
│ │ ├── topic_form.js
│ │ ├── collaborators.js
│ │ ├── application.js
│ │ ├── spin.min.js
│ │ └── jquery.hotkeys.js
│ └── stylesheets
│ │ ├── jquery.minicolors.png
│ │ ├── imgareaselect-css
│ │ ├── border-h.gif
│ │ ├── border-v.gif
│ │ ├── border-anim-h.gif
│ │ ├── border-anim-v.gif
│ │ ├── imgareaselect-deprecated.css
│ │ ├── imgareaselect-default.css
│ │ └── imgareaselect-animated.css
│ │ ├── home.css.scss
│ │ ├── threads.css.scss
│ │ ├── bootstrap_and_overrides.css.less
│ │ ├── coding.css.scss
│ │ └── application.css
├── views
│ ├── media
│ │ ├── new.html.erb
│ │ ├── edit.html.erb
│ │ ├── show.html.erb
│ │ ├── index.html.erb
│ │ └── _form.html.erb
│ ├── images
│ │ ├── new.html.erb
│ │ ├── edit.html.erb
│ │ ├── _form.html.erb
│ │ ├── show.html.erb
│ │ └── index.html.erb
│ ├── users
│ │ ├── edit.html.erb
│ │ ├── new.html.erb
│ │ ├── _form.html.erb
│ │ ├── show.html.erb
│ │ └── index.html.erb
│ ├── devise
│ │ ├── mailer
│ │ │ ├── confirmation_instructions.html.erb
│ │ │ ├── unlock_instructions.html.erb
│ │ │ └── reset_password_instructions.html.erb
│ │ ├── unlocks
│ │ │ └── new.html.erb
│ │ ├── passwords
│ │ │ ├── new.html.erb
│ │ │ └── edit.html.erb
│ │ ├── confirmations
│ │ │ └── new.html.erb
│ │ ├── sessions
│ │ │ └── new.html.erb
│ │ ├── registrations
│ │ │ ├── new.html.erb
│ │ │ └── edit.html.erb
│ │ └── _links.erb
│ ├── coding
│ │ ├── _coding_footer.html.erb
│ │ └── embed.html.erb
│ ├── home
│ │ ├── help.html.erb
│ │ ├── about.html.erb
│ │ └── index.html.erb
│ ├── taxonomies
│ │ ├── new.html.erb
│ │ ├── index.html.erb
│ │ └── edit.html.erb
│ ├── taxonomy_options
│ │ ├── _form.html.erb
│ │ ├── edit.html.erb
│ │ └── index.html.erb
│ ├── threads
│ │ ├── _topic_form.html.erb
│ │ └── index.html.erb
│ └── layouts
│ │ └── embed.html.erb
└── controllers
│ ├── home_controller.rb
│ ├── application_controller.rb
│ ├── taxonomies_controller.rb
│ ├── taxonomy_options_controller.rb
│ ├── users_controller.rb
│ ├── media_controller.rb
│ └── images_controller.rb
├── vendor
├── plugins
│ └── .gitkeep
└── assets
│ ├── javascripts
│ └── .gitkeep
│ └── stylesheets
│ └── .gitkeep
├── .ruby-gemset
├── .ruby-version
├── .env
├── docker-ruby
├── v1.9.3
│ ├── REVISION
│ ├── Makefile
│ └── Dockerfile
├── Makefile.main
└── README.md
├── docker-compose-files
├── pageonex.cnf
├── pageonex-build.cnf
└── wrap-start-app.sh
├── favicon.ico
├── public
├── favicon.ico
├── nothing-to-code.png
├── robots.txt
├── 500.html
├── 422.html
└── 404.html
├── .dockerignore
├── release-tasks.sh
├── config
├── local_env.yml
├── initializers
│ ├── abstract_mysql2_adapter.rb
│ ├── mime_types.rb
│ ├── application.rb
│ ├── backtrace_silencers.rb
│ ├── session_store.rb
│ ├── secret_token.rb
│ ├── wrap_parameters.rb
│ └── inflections.rb
├── boot.rb
├── locales
│ ├── en.yml
│ ├── en.bootstrap.yml
│ └── devise.en.yml
├── environment.rb
├── piwik.yml
├── database.yml
├── environments
│ ├── test.rb
│ ├── development.rb
│ └── production.rb
├── puma.rb
├── routes.rb
└── application.rb
├── spec
├── controllers
│ ├── coding_controller_spec.rb
│ ├── threads_controller_spec.rb
│ └── home_controller_spec.rb
├── models
│ ├── area_spec.rb
│ ├── code_spec.rb
│ ├── image_spec.rb
│ ├── media_spec.rb
│ ├── user_spec.rb
│ ├── threadx_spec.rb
│ ├── coded_page_spec.rb
│ ├── image_code_spec.rb
│ ├── media_threadx_spec.rb
│ ├── threadx_image_spec.rb
│ ├── highlighted_area_spec.rb
│ └── threadx_collaborator_spec.rb
├── factories
│ ├── users.rb
│ ├── codes.rb
│ ├── image_codes.rb
│ ├── media_threadxes.rb
│ ├── threadx_collaborators.rb
│ ├── coded_pages.rb
│ ├── threadx_images.rb
│ ├── areas.rb
│ ├── highlighted_areas.rb
│ ├── images.rb
│ ├── media.rb
│ └── threadxes.rb
├── views
│ ├── home
│ │ └── index.html.erb_spec.rb
│ ├── users
│ │ ├── show.html.erb_spec.rb
│ │ ├── index.html.erb_spec.rb
│ │ ├── new.html.erb_spec.rb
│ │ └── edit.html.erb_spec.rb
│ ├── images
│ │ ├── show.html.erb_spec.rb
│ │ ├── index.html.erb_spec.rb
│ │ ├── new.html.erb_spec.rb
│ │ └── edit.html.erb_spec.rb
│ └── media
│ │ ├── show.html.erb_spec.rb
│ │ ├── new.html.erb_spec.rb
│ │ ├── edit.html.erb_spec.rb
│ │ └── index.html.erb_spec.rb
├── requests
│ ├── images_spec.rb
│ ├── media_spec.rb
│ └── users_spec.rb
├── helpers
│ ├── home_helper_spec.rb
│ ├── media_helper_spec.rb
│ ├── users_helper_spec.rb
│ ├── coding_helper_spec.rb
│ ├── images_helper_spec.rb
│ ├── thread_helper_spec.rb
│ └── threads_helper_spec.rb
└── routing
│ ├── media_routing_spec.rb
│ ├── users_routing_spec.rb
│ └── images_routing_spec.rb
├── db
├── migrate
│ ├── 20140516094821_add_bio_to_users.rb
│ ├── 20130429213553_add_admin_to_users.rb
│ ├── 20120704184911_add_color_to_code.rb
│ ├── 20120706030854_add_width_to_area.rb
│ ├── 20120706030926_add_height_to_area.rb
│ ├── 20130327162055_add_missing_to_image.rb
│ ├── 20130709193435_remove_image_local_path.rb
│ ├── 20120717230420_change_size_type_in_image.rb
│ ├── 20130309271421_fix_column_media_name.rb
│ ├── 20130322201029_add_source_url_to_image.rb
│ ├── 20120706131048_add_image_name_to_image.rb
│ ├── 20180703105721_add_parent_id_to_threads.rb
│ ├── 20120628160725_add_display_name_to_media.rb
│ ├── 20130328193053_add_working_to_media.rb
│ ├── 20120704183326_add_code_description_to_code.rb
│ ├── 20120713215917_add_name_to_highlighted_area.rb
│ ├── 20120716010022_add_threadx_id_to_highlighted_area.rb
│ ├── 20180705090755_create_taxonomies.rb
│ ├── 20120627142557_create_codes.rb
│ ├── 20120707072202_rename_threadx_image_id_to_code_id_from_highlighted_area.rb
│ ├── 20120707072849_create_image_codes.rb
│ ├── 20120627163234_create_media_threadxes.rb
│ ├── 20180705090834_create_taxonomy_options.rb
│ ├── 20180706092346_create_threadx_taxonomies.rb
│ ├── 20120627142119_create_media.rb
│ ├── 20120627151823_create_threadx_collaborators.rb
│ ├── 20130306175244_create_coded_pages.rb
│ ├── 20120627151947_create_threadx_images.rb
│ ├── 20130225233225_remove_threadx_id_from_highlighted_area.rb
│ ├── 20120627143712_create_images.rb
│ ├── 20120627142446_create_highlighted_areas.rb
│ ├── 20120627142253_create_areas.rb
│ ├── 20180706092525_create_taxonomy_classifications.rb
│ ├── 20130225162431_drop_image_codes.rb
│ ├── 20130220214404_drop_threadx_images.rb
│ ├── 20120627141933_create_threadxes.rb
│ └── 20120627130452_devise_create_users.rb
└── seeds.rb
├── app.json
├── config.ru
├── Rakefile
├── script
└── rails
├── Dockerfile
├── .project
├── .travis.yml
├── .gitignore
├── Makefile
├── docker-compose-build.yml
├── docker-compose.yml
├── Gemfile
└── doc
├── docker
├── running-pageonex-in-your-environment.md
├── running-pageonex-locally-with-docker-compose.md
└── development-with-docker-compose.md
└── local-install.md
/log/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/tasks/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/mailers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/plugins/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.ruby-gemset:
--------------------------------------------------------------------------------
1 | pageonex
2 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | ruby-1.9.3
2 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | RACK_ENV=development
2 |
--------------------------------------------------------------------------------
/docker-ruby/v1.9.3/REVISION:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/helpers/home_helper.rb:
--------------------------------------------------------------------------------
1 | module HomeHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/users_helper.rb:
--------------------------------------------------------------------------------
1 | module UsersHelper
2 | end
3 |
--------------------------------------------------------------------------------
/docker-ruby/v1.9.3/Makefile:
--------------------------------------------------------------------------------
1 | -include ../Makefile.main
2 |
--------------------------------------------------------------------------------
/app/helpers/coding_helper.rb:
--------------------------------------------------------------------------------
1 | module CodingHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/images_helper.rb:
--------------------------------------------------------------------------------
1 | module ImagesHelper
2 | end
3 |
--------------------------------------------------------------------------------
/docker-compose-files/pageonex.cnf:
--------------------------------------------------------------------------------
1 | [mysqld]
2 | port=13306
3 |
--------------------------------------------------------------------------------
/docker-compose-files/pageonex-build.cnf:
--------------------------------------------------------------------------------
1 | [mysqld]
2 | port=23306
3 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | docker-compose.yml
3 | doc
4 | *.md
5 | docker-ruby
6 | docker-compose-files
7 |
--------------------------------------------------------------------------------
/app/assets/images/404.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/404.jpg
--------------------------------------------------------------------------------
/app/assets/images/rails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/rails.png
--------------------------------------------------------------------------------
/public/nothing-to-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/public/nothing-to-code.png
--------------------------------------------------------------------------------
/app/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/favicon.ico
--------------------------------------------------------------------------------
/release-tasks.sh:
--------------------------------------------------------------------------------
1 | rake db:migrate
2 | rake scraping:update_media
3 | rake bundle exec rake assets:precompile
4 |
--------------------------------------------------------------------------------
/app/assets/images/icon-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/icon-close.png
--------------------------------------------------------------------------------
/app/assets/images/icon-edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/icon-edit.png
--------------------------------------------------------------------------------
/app/assets/images/header-blog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/header-blog.png
--------------------------------------------------------------------------------
/app/assets/images/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/transparent.png
--------------------------------------------------------------------------------
/app/assets/images/twitter-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/twitter-icon.png
--------------------------------------------------------------------------------
/app/assets/images/youtube-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/youtube-icon.png
--------------------------------------------------------------------------------
/app/helpers/media_helper.rb:
--------------------------------------------------------------------------------
1 | module MediaHelper
2 |
3 | def media_index_path arg
4 | '/media'
5 | end
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/app/models/code.rb:
--------------------------------------------------------------------------------
1 | class Code < ActiveRecord::Base
2 | belongs_to :threadx
3 | has_many :highlighted_areas
4 | end
5 |
--------------------------------------------------------------------------------
/config/local_env.yml:
--------------------------------------------------------------------------------
1 | # ImageMagick settings
2 |
3 | # yield the cpu in chunks of this many ms
4 | MAGICK_THROTTLE: '1'
5 |
--------------------------------------------------------------------------------
/spec/controllers/coding_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe CodingController do
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/spec/controllers/threads_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ThreadsController do
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/app/assets/images/header-blog-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/header-blog-2.png
--------------------------------------------------------------------------------
/app/assets/images/wordpress-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/wordpress-icon.png
--------------------------------------------------------------------------------
/app/models/media_threadx.rb:
--------------------------------------------------------------------------------
1 | class MediaThreadx < ActiveRecord::Base
2 | belongs_to :threadx
3 | belongs_to :media
4 | end
5 |
--------------------------------------------------------------------------------
/app/assets/images/imago-pageonex-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/imago-pageonex-1.png
--------------------------------------------------------------------------------
/app/assets/images/imago-pageonex-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/imago-pageonex-2.png
--------------------------------------------------------------------------------
/app/assets/images/imago-pageonex-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/imago-pageonex-3.png
--------------------------------------------------------------------------------
/app/assets/images/imago-pageonex-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/imago-pageonex-4.png
--------------------------------------------------------------------------------
/app/assets/images/detail-front-pages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/images/detail-front-pages.png
--------------------------------------------------------------------------------
/app/assets/javascripts/images/colors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/javascripts/images/colors.png
--------------------------------------------------------------------------------
/app/assets/javascripts/images/trigger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/javascripts/images/trigger.png
--------------------------------------------------------------------------------
/app/assets/stylesheets/jquery.minicolors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/stylesheets/jquery.minicolors.png
--------------------------------------------------------------------------------
/app/models/threadx_collaborator.rb:
--------------------------------------------------------------------------------
1 | class ThreadxCollaborator < ActiveRecord::Base
2 | belongs_to :threadx
3 | belongs_to :user
4 | end
5 |
--------------------------------------------------------------------------------
/spec/models/area_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Area do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/code_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Code do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/image_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Image do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/media_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Media do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/user_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe User do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/app/assets/javascripts/bootstrap.js.coffee:
--------------------------------------------------------------------------------
1 | jQuery ->
2 | $("a[rel=popover]").popover()
3 | $(".tooltip").tooltip()
4 | $("a[rel=tooltip]").tooltip()
--------------------------------------------------------------------------------
/spec/models/threadx_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Threadx do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/coded_page_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe CodedPage do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/image_code_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ImageCode do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/imgareaselect-css/border-h.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/stylesheets/imgareaselect-css/border-h.gif
--------------------------------------------------------------------------------
/app/assets/stylesheets/imgareaselect-css/border-v.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/stylesheets/imgareaselect-css/border-v.gif
--------------------------------------------------------------------------------
/spec/models/media_threadx_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe MediaThreadx do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/threadx_image_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ThreadxImage do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/app/views/media/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "New Media - PageOneX" %>
2 |
New Media
3 |
4 | <%= render 'form' %>
5 |
6 | <%= link_to 'Back', media_path %>
7 |
--------------------------------------------------------------------------------
/spec/factories/users.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :user do
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/models/highlighted_area_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe HighlightedArea do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/imgareaselect-css/border-anim-h.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/stylesheets/imgareaselect-css/border-anim-h.gif
--------------------------------------------------------------------------------
/app/assets/stylesheets/imgareaselect-css/border-anim-v.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/montera34/pageonex/HEAD/app/assets/stylesheets/imgareaselect-css/border-anim-v.gif
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 |
3 | def use_local_images
4 | Pageonex::Application.config.use_local_images
5 | end
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20140516094821_add_bio_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddBioToUsers < ActiveRecord::Migration
2 | def change
3 | add_column :users, :bio, :text
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130429213553_add_admin_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddAdminToUsers < ActiveRecord::Migration
2 | def change
3 | add_column :users, :admin, :boolean
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/threadx_collaborator_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ThreadxCollaborator do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/views/home/index.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "home/index.html.erb" do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "PageOneX",
3 | "description": "",
4 | "scripts": {
5 | "dokku": {
6 | "predepploy": "./release-tasks.sh"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run Pageonex::Application
5 |
--------------------------------------------------------------------------------
/db/migrate/20120704184911_add_color_to_code.rb:
--------------------------------------------------------------------------------
1 | class AddColorToCode < ActiveRecord::Migration
2 | def change
3 | add_column :codes, :color, :string
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20120706030854_add_width_to_area.rb:
--------------------------------------------------------------------------------
1 | class AddWidthToArea < ActiveRecord::Migration
2 | def change
3 | add_column :areas, :width, :integer
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/models/taxonomy.rb:
--------------------------------------------------------------------------------
1 | class Taxonomy < ActiveRecord::Base
2 | has_many :taxonomy_options, dependent: :destroy
3 |
4 | validates :name, presence: true, uniqueness: true
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120706030926_add_height_to_area.rb:
--------------------------------------------------------------------------------
1 | class AddHeightToArea < ActiveRecord::Migration
2 | def change
3 | add_column :areas, :height, :integer
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20130327162055_add_missing_to_image.rb:
--------------------------------------------------------------------------------
1 | class AddMissingToImage < ActiveRecord::Migration
2 | def change
3 | add_column :images, :missing, :boolean
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130709193435_remove_image_local_path.rb:
--------------------------------------------------------------------------------
1 | class RemoveImageLocalPath < ActiveRecord::Migration
2 | def change
3 | remove_column :images, :local_path
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/config/initializers/abstract_mysql2_adapter.rb:
--------------------------------------------------------------------------------
1 | class ActiveRecord::ConnectionAdapters::Mysql2Adapter
2 | NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
3 | end
4 |
--------------------------------------------------------------------------------
/db/migrate/20120717230420_change_size_type_in_image.rb:
--------------------------------------------------------------------------------
1 | class ChangeSizeTypeInImage < ActiveRecord::Migration
2 | def change
3 | change_column :images, :size, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130309271421_fix_column_media_name.rb:
--------------------------------------------------------------------------------
1 | class FixColumnMediaName < ActiveRecord::Migration
2 | def change
3 | rename_column :media, :city, :country_code
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130322201029_add_source_url_to_image.rb:
--------------------------------------------------------------------------------
1 | class AddSourceUrlToImage < ActiveRecord::Migration
2 | def change
3 | add_column :images, :source_url, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120706131048_add_image_name_to_image.rb:
--------------------------------------------------------------------------------
1 | class AddImageNameToImage < ActiveRecord::Migration
2 | def change
3 | add_column :images, :image_name, :string
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20180703105721_add_parent_id_to_threads.rb:
--------------------------------------------------------------------------------
1 | class AddParentIdToThreads < ActiveRecord::Migration
2 | def change
3 | add_column :threadxes, :parent_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120628160725_add_display_name_to_media.rb:
--------------------------------------------------------------------------------
1 | class AddDisplayNameToMedia < ActiveRecord::Migration
2 | def change
3 | add_column :media, :display_name, :string
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20130328193053_add_working_to_media.rb:
--------------------------------------------------------------------------------
1 | class AddWorkingToMedia < ActiveRecord::Migration
2 | def change
3 | add_column :media, :working, :boolean, {:default=>true}
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/models/threadx_taxonomy.rb:
--------------------------------------------------------------------------------
1 | class ThreadxTaxonomy < ActiveRecord::Base
2 | belongs_to :threadx
3 | belongs_to :taxonomy
4 |
5 | validates :taxonomy_id, uniqueness: { scope: :threadx_id }
6 | end
7 |
--------------------------------------------------------------------------------
/app/views/media/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Edit medium - PageOneX" %>
2 | Editing medium
3 |
4 | <%= render 'form' %>
5 |
6 | <%= link_to 'Show', @media %> |
7 | <%= link_to 'Back', media_path %>
8 |
--------------------------------------------------------------------------------
/db/migrate/20120704183326_add_code_description_to_code.rb:
--------------------------------------------------------------------------------
1 | class AddCodeDescriptionToCode < ActiveRecord::Migration
2 | def change
3 | add_column :codes, :code_description, :text
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20120713215917_add_name_to_highlighted_area.rb:
--------------------------------------------------------------------------------
1 | class AddNameToHighlightedArea < ActiveRecord::Migration
2 | def change
3 | add_column :highlighted_areas, :name, :string
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/codes.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :code do
5 | code_text "MyString"
6 | threadx_id 1
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/factories/image_codes.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :image_code do
5 | image_id 1
6 | code_id 1
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/home.css.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the home controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/spec/factories/media_threadxes.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :media_threadx do
5 | threadx_id 1
6 | media_id 1
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 |
3 | # Set up gems listed in the Gemfile.
4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5 |
6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
7 |
--------------------------------------------------------------------------------
/db/migrate/20120716010022_add_threadx_id_to_highlighted_area.rb:
--------------------------------------------------------------------------------
1 | class AddThreadxIdToHighlightedArea < ActiveRecord::Migration
2 | def change
3 | add_column :highlighted_areas, :threadx_id, :integer
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-Agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/spec/factories/threadx_collaborators.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :threadx_collaborator do
5 | threadx_id 1
6 | user_id 1
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/factories/coded_pages.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :coded_page do
5 | threadx_id 1
6 | user_id 1
7 | image_id 1
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20180705090755_create_taxonomies.rb:
--------------------------------------------------------------------------------
1 | class CreateTaxonomies < ActiveRecord::Migration
2 | def change
3 | create_table :taxonomies do |t|
4 | t.string :name
5 |
6 | t.timestamps
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | hello: "Hello world"
6 |
--------------------------------------------------------------------------------
/spec/factories/threadx_images.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :threadx_image do
5 | threadx_id 1
6 | image_id 1
7 | code_id 1
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/factories/areas.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :area do
5 | x1 1
6 | y1 1
7 | x2 1
8 | y2 1
9 | highlighted_area_id 1
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/spec/factories/highlighted_areas.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :highlighted_area do
5 | image_id 1
6 | user_id 1
7 | threadx_image_id 1
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20120627142557_create_codes.rb:
--------------------------------------------------------------------------------
1 | class CreateCodes < ActiveRecord::Migration
2 | def change
3 | create_table :codes do |t|
4 | t.string :code_text
5 | t.integer :threadx_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/factories/images.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :image do
5 | type ""
6 | publication_date "2012-06-27"
7 | size 1
8 | media_id 1
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/assets/javascripts/home.js.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
4 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the rails application
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the rails application
5 | Pageonex::Application.initialize!
6 |
7 | Mime::Type.register "application/x-vnd.oasis.opendocument.spreadsheet", :ods
--------------------------------------------------------------------------------
/db/migrate/20120707072202_rename_threadx_image_id_to_code_id_from_highlighted_area.rb:
--------------------------------------------------------------------------------
1 | class RenameThreadxImageIdToCodeIdFromHighlightedArea < ActiveRecord::Migration
2 | def change
3 | rename_column :highlighted_areas, :threadx_image_id, :code_id
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/controllers/home_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe HomeController do
4 |
5 | describe "GET 'index'" do
6 | it "returns http success" do
7 | get 'index'
8 | response.should be_success
9 | end
10 | end
11 |
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20120707072849_create_image_codes.rb:
--------------------------------------------------------------------------------
1 | class CreateImageCodes < ActiveRecord::Migration
2 | def change
3 | create_table :image_codes do |t|
4 | t.integer :image_id
5 | t.integer :code_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/assets/javascripts/threads.js.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/assets/javascripts/utils.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 |
3 | $(".js-toggle-elements").click(function(){
4 | show_id = $(this).data('show');
5 | hide_id = $(this).data('hide');
6 | $('#'+show_id).show();
7 | $('#'+hide_id).hide();
8 | });
9 |
10 | });
11 |
--------------------------------------------------------------------------------
/app/models/taxonomy_option.rb:
--------------------------------------------------------------------------------
1 | class TaxonomyOption < ActiveRecord::Base
2 | belongs_to :taxonomy
3 | has_many :taxonomy_classifications, dependent: :destroy
4 |
5 | validates :value, presence: true, uniqueness: { scope: :taxonomy_id }
6 | validates :taxonomy_id, presence: true
7 | end
8 |
--------------------------------------------------------------------------------
/spec/factories/media.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :medium, :class => 'Media' do
5 | name "MyString"
6 | country "MyString"
7 | city "MyString"
8 | url "MyString"
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20120627163234_create_media_threadxes.rb:
--------------------------------------------------------------------------------
1 | class CreateMediaThreadxes < ActiveRecord::Migration
2 | def change
3 | create_table :media_threadxes do |t|
4 | t.integer :threadx_id
5 | t.integer :media_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20180705090834_create_taxonomy_options.rb:
--------------------------------------------------------------------------------
1 | class CreateTaxonomyOptions < ActiveRecord::Migration
2 | def change
3 | create_table :taxonomy_options do |t|
4 | t.string :value
5 | t.integer :taxonomy_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/views/images/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "New image - PageOneX" %>
2 | <%- model_class = Image -%>
3 |
6 | <%= render :partial => 'form' %>
7 |
--------------------------------------------------------------------------------
/app/views/users/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Edit user - PageOneX" %>
2 | <%- model_class = User -%>
3 |
6 | <%= render :partial => 'form' %>
7 |
--------------------------------------------------------------------------------
/app/views/users/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "User page - PageOneX" %>
2 | <%- model_class = User -%>
3 |
6 | <%= render :partial => 'form' %>
7 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 | Mime::Type.register "image/svg+xml", :svg
7 |
--------------------------------------------------------------------------------
/db/migrate/20180706092346_create_threadx_taxonomies.rb:
--------------------------------------------------------------------------------
1 | class CreateThreadxTaxonomies < ActiveRecord::Migration
2 | def change
3 | create_table :threadx_taxonomies do |t|
4 | t.integer :threadx_id
5 | t.integer :taxonomy_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path('../config/application', __FILE__)
6 |
7 | Pageonex::Application.load_tasks
8 |
--------------------------------------------------------------------------------
/app/views/images/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Image edit - PageOneX" %>
2 | <%- model_class = Image -%>
3 |
6 | <%= render :partial => 'form' %>
7 |
--------------------------------------------------------------------------------
/db/migrate/20120627142119_create_media.rb:
--------------------------------------------------------------------------------
1 | class CreateMedia < ActiveRecord::Migration
2 | def change
3 | create_table :media do |t|
4 | t.string :name
5 | t.string :country
6 | t.string :city
7 | t.string :url
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20120627151823_create_threadx_collaborators.rb:
--------------------------------------------------------------------------------
1 | class CreateThreadxCollaborators < ActiveRecord::Migration
2 | def change
3 | create_table :threadx_collaborators do |t|
4 | t.integer :threadx_id
5 | t.integer :user_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20130306175244_create_coded_pages.rb:
--------------------------------------------------------------------------------
1 | class CreateCodedPages < ActiveRecord::Migration
2 | def change
3 | create_table :coded_pages do |t|
4 | t.integer :threadx_id
5 | t.integer :user_id
6 | t.integer :image_id
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20120627151947_create_threadx_images.rb:
--------------------------------------------------------------------------------
1 | class CreateThreadxImages < ActiveRecord::Migration
2 | def change
3 | create_table :threadx_images do |t|
4 | t.integer :threadx_id
5 | t.integer :image_id
6 | t.integer :code_id
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20130225233225_remove_threadx_id_from_highlighted_area.rb:
--------------------------------------------------------------------------------
1 | class RemoveThreadxIdFromHighlightedArea < ActiveRecord::Migration
2 | def up
3 | remove_column :highlighted_areas, :threadx_id
4 | end
5 |
6 | def down
7 | add_column :highlighted_areas, :threadx_id, :integer
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | APP_PATH = File.expand_path('../../config/application', __FILE__)
5 | require File.expand_path('../../config/boot', __FILE__)
6 | require 'rails/commands'
7 |
--------------------------------------------------------------------------------
/db/migrate/20120627143712_create_images.rb:
--------------------------------------------------------------------------------
1 | class CreateImages < ActiveRecord::Migration
2 | def change
3 | create_table :images do |t|
4 | t.date :publication_date
5 | t.integer :size
6 | t.string :local_path
7 | t.integer :media_id
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20120627142446_create_highlighted_areas.rb:
--------------------------------------------------------------------------------
1 | class CreateHighlightedAreas < ActiveRecord::Migration
2 | def change
3 | create_table :highlighted_areas do |t|
4 | t.integer :image_id
5 | t.integer :user_id
6 | t.integer :threadx_image_id
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/threads.css.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the threads controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 |
5 | .topic_color_box {
6 | margin-bottom: 10px;
7 | }
8 |
9 | ul#collab-list {
10 | margin-top: 1em;
11 | }
--------------------------------------------------------------------------------
/db/migrate/20120627142253_create_areas.rb:
--------------------------------------------------------------------------------
1 | class CreateAreas < ActiveRecord::Migration
2 | def change
3 | create_table :areas do |t|
4 | t.integer :x1
5 | t.integer :y1
6 | t.integer :x2
7 | t.integer :y2
8 | t.integer :highlighted_area_id
9 |
10 | t.timestamps
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20180706092525_create_taxonomy_classifications.rb:
--------------------------------------------------------------------------------
1 | class CreateTaxonomyClassifications < ActiveRecord::Migration
2 | def change
3 | create_table :taxonomy_classifications do |t|
4 | t.integer :highlighted_area_id
5 | t.integer :taxonomy_option_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
12 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/confirmation_instructions.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Welcome email - PageOneX" %>
2 | Welcome <%= @resource.email %>!
3 |
4 | You can confirm your account email through the link below:
5 |
6 | <%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %>
7 |
--------------------------------------------------------------------------------
/spec/views/users/show.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "users/show" do
4 | before(:each) do
5 | @user = assign(:user, stub_model(User))
6 | end
7 |
8 | it "renders attributes in " do
9 | render
10 | # Run the generator again with the --webrat flag if you want to use webrat matchers
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/models/coded_page.rb:
--------------------------------------------------------------------------------
1 | class CodedPage < ActiveRecord::Base
2 | belongs_to :threadx
3 | has_one :user
4 | has_one :image
5 |
6 | def self.for_user(user)
7 | return where(1) if user.nil?
8 | where(:user_id => user.id)
9 | end
10 |
11 | def self.for_image(image)
12 | where(:image_id => image.id)
13 | end
14 |
15 | end
16 |
--------------------------------------------------------------------------------
/spec/views/images/show.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "images/show" do
4 | before(:each) do
5 | @image = assign(:image, stub_model(Image))
6 | end
7 |
8 | it "renders attributes in
" do
9 | render
10 | # Run the generator again with the --webrat flag if you want to use webrat matchers
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/requests/images_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Images" do
4 | describe "GET /images" do
5 | it "works! (now write some real specs)" do
6 | # Run the generator again with the --webrat flag if you want to use webrat methods/matchers
7 | get images_path
8 | response.status.should be(200)
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/spec/requests/media_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Media" do
4 | describe "GET /media" do
5 | it "works! (now write some real specs)" do
6 | # Run the generator again with the --webrat flag if you want to use webrat methods/matchers
7 | get media_path
8 | response.status.should be(200)
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/spec/requests/users_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Users" do
4 | describe "GET /users" do
5 | it "works! (now write some real specs)" do
6 | # Run the generator again with the --webrat flag if you want to use webrat methods/matchers
7 | get users_path
8 | response.status.should be(200)
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/docker-ruby/Makefile.main:
--------------------------------------------------------------------------------
1 | PROJECT = ruby-base
2 | DOCKER_REGISTRY = docker.io
3 | DOCKER_ORG = pageonex
4 | VERSION := $(shell echo `basename "$(PWD)"`.`cat REVISION`)
5 | DOCKER_IMAGE = $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT):$(VERSION)
6 |
7 | docker-build:
8 | docker build -t $(DOCKER_IMAGE) .
9 |
10 | docker-push: docker-build
11 | docker push $(DOCKER_IMAGE)
12 |
--------------------------------------------------------------------------------
/spec/factories/threadxes.rb:
--------------------------------------------------------------------------------
1 | # Read about factories at https://github.com/thoughtbot/factory_girl
2 |
3 | FactoryGirl.define do
4 | factory :threadx do
5 | thread_name "MyString"
6 | thread_display_name "MyString"
7 | start_date "2012-06-27"
8 | end_date "2012-06-27"
9 | description "MyText"
10 | category "MyString"
11 | status "MyString"
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/views/users/index.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "users/index" do
4 | before(:each) do
5 | assign(:users, [
6 | stub_model(User),
7 | stub_model(User)
8 | ])
9 | end
10 |
11 | it "renders a list of users" do
12 | render
13 | # Run the generator again with the --webrat flag if you want to use webrat matchers
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/views/images/index.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "images/index" do
4 | before(:each) do
5 | assign(:images, [
6 | stub_model(Image),
7 | stub_model(Image)
8 | ])
9 | end
10 |
11 | it "renders a list of images" do
12 | render
13 | # Run the generator again with the --webrat flag if you want to use webrat matchers
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/home_controller.rb:
--------------------------------------------------------------------------------
1 | class HomeController < ApplicationController
2 | def index
3 | @threads = Threadx.limit(16)
4 | end
5 | def about
6 |
7 | end
8 | def export_chart
9 | Tempfile.open(['chart', '.svg'], Rails.root.join('tmp')) do |f|
10 | f.print params[:svgdata]
11 | f.flush
12 | send_file f.path, :type => 'image/svg+xml'
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20130225162431_drop_image_codes.rb:
--------------------------------------------------------------------------------
1 | class DropImageCodes < ActiveRecord::Migration
2 | def up
3 | drop_table :image_codes
4 | end
5 |
6 | def down
7 | create_table(:threadx_images) do |t|
8 | t.integer "image_id"
9 | t.integer "code_id"
10 | t.datetime "created_at", :null => false
11 | t.datetime "updated_at", :null => false
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM pageonex/ruby-base:v1.9.3.2
2 |
3 | ENV PATH $PATH:/usr/lib/x86_64-linux-gnu/ImageMagick-6.8.9/bin-Q16/
4 |
5 | WORKDIR /tmp
6 | ADD ./Gemfile Gemfile
7 | ADD ./Gemfile.lock Gemfile.lock
8 | RUN bundle install
9 |
10 | ENV APP_ROOT /workspace
11 | RUN mkdir -p $APP_ROOT
12 | WORKDIR $APP_ROOT
13 | COPY . $APP_ROOT
14 |
15 | EXPOSE 3000
16 | CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
17 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/unlock_instructions.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Unlock password instructions - PageOneX" %>
2 |
Hello <%= @resource.email %>!
3 |
4 | Your account has been locked due to an excessive amount of unsuccessful sign in attempts.
5 |
6 | Click the link below to unlock your account:
7 |
8 | <%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token) %>
9 |
--------------------------------------------------------------------------------
/app/views/devise/unlocks/new.html.erb:
--------------------------------------------------------------------------------
1 | Resend unlock instructions
2 |
3 | <%= form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
4 | <%= devise_error_messages! %>
5 |
6 | <%= f.label :email %>
7 | <%= f.email_field :email %>
8 |
9 | <%= f.submit "Resend unlock instructions" %>
10 | <% end %>
11 |
12 | <%= render "links" %>
--------------------------------------------------------------------------------
/spec/views/users/new.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "users/new" do
4 | before(:each) do
5 | assign(:user, stub_model(User).as_new_record)
6 | end
7 |
8 | it "renders new user form" do
9 | render
10 |
11 | # Run the generator again with the --webrat flag if you want to use webrat matchers
12 | assert_select "form[action=?][method=?]", users_path, "post" do
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/views/images/new.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "images/new" do
4 | before(:each) do
5 | assign(:image, stub_model(Image).as_new_record)
6 | end
7 |
8 | it "renders new image form" do
9 | render
10 |
11 | # Run the generator again with the --webrat flag if you want to use webrat matchers
12 | assert_select "form[action=?][method=?]", images_path, "post" do
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/views/users/edit.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "users/edit" do
4 | before(:each) do
5 | @user = assign(:user, stub_model(User))
6 | end
7 |
8 | it "renders the edit user form" do
9 | render
10 |
11 | # Run the generator again with the --webrat flag if you want to use webrat matchers
12 | assert_select "form[action=?][method=?]", user_path(@user), "post" do
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20130220214404_drop_threadx_images.rb:
--------------------------------------------------------------------------------
1 | class DropThreadxImages < ActiveRecord::Migration
2 | def up
3 | drop_table :threadx_images
4 | end
5 |
6 | def down
7 | create_table(:threadx_images) do |t|
8 | t.integer "threadx_id"
9 | t.integer "image_id"
10 | t.integer "code_id"
11 | t.datetime "created_at", :null => false
12 | t.datetime "updated_at", :null => false
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20120627141933_create_threadxes.rb:
--------------------------------------------------------------------------------
1 | class CreateThreadxes < ActiveRecord::Migration
2 | def change
3 | create_table :threadxes do |t|
4 | t.string :thread_name
5 | t.string :thread_display_name
6 | t.date :start_date
7 | t.date :end_date
8 | t.text :description
9 | t.string :category
10 | t.string :status
11 | t.integer :owner_id
12 |
13 | t.timestamps
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/spec/views/images/edit.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "images/edit" do
4 | before(:each) do
5 | @image = assign(:image, stub_model(Image))
6 | end
7 |
8 | it "renders the edit image form" do
9 | render
10 |
11 | # Run the generator again with the --webrat flag if you want to use webrat matchers
12 | assert_select "form[action=?][method=?]", image_path(@image), "post" do
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/config/initializers/application.rb:
--------------------------------------------------------------------------------
1 |
2 | # should we cache the kiosko image files locally, or just show them directly from kiosko's domain?
3 | Pageonex::Application.config.use_local_images = true
4 |
5 | # date format used by kiosko to name their newspaper frontpage image files
6 | Date::DATE_FORMATS[:kiosko_file_datestamp]="%Y/%m/%d"
7 |
8 | # date format we use to create the locally downloaded images
9 | Time::DATE_FORMATS[:file_datestamp] = "%Y-%m-%d"
10 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/app/helpers/thread_helper.rb:
--------------------------------------------------------------------------------
1 | module ThreadHelper
2 |
3 | # use this to link to a thread
4 | def thread_code_url thread, image_name=nil
5 | link = thread_url(thread) + "coding"
6 | link+= "/?i=#{image_name}" unless image_name.nil?
7 | link
8 | end
9 |
10 | def thread_url thread
11 | thread.link_url
12 | end
13 |
14 | def threads_by_user_link user
15 | link_to user.username, '/threads/by/'+user.username
16 | end
17 |
18 | end
19 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Pageonex::Application.config.session_store :cookie_store, key: '_pageonex_session'
4 |
5 | # Use the database for sessions instead of the cookie-based default,
6 | # which shouldn't be used to store highly confidential information
7 | # (create the session table with "rails generate session_migration")
8 | # Pageonex::Application.config.session_store :active_record_store
9 |
--------------------------------------------------------------------------------
/spec/helpers/home_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the HomeHelper. For example:
5 | #
6 | # describe HomeHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # helper.concat_strings("this","that").should == "this that"
10 | # end
11 | # end
12 | # end
13 | describe HomeHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/app/views/devise/passwords/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Reset password action - PageOneX" %>
2 | Forgot your password?
3 |
4 | <%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
5 | <%= devise_error_messages! %>
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email %>
9 |
10 | <%= f.submit "Send me reset password instructions" %>
11 | <% end %>
12 |
13 | <%= render "links" %>
14 |
--------------------------------------------------------------------------------
/spec/helpers/media_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the MediaHelper. For example:
5 | #
6 | # describe MediaHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # helper.concat_strings("this","that").should == "this that"
10 | # end
11 | # end
12 | # end
13 | describe MediaHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/spec/helpers/users_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the UsersHelper. For example:
5 | #
6 | # describe UsersHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # helper.concat_strings("this","that").should == "this that"
10 | # end
11 | # end
12 | # end
13 | describe UsersHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/spec/helpers/coding_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the CodingHelper. For example:
5 | #
6 | # describe CodingHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # helper.concat_strings("this","that").should == "this that"
10 | # end
11 | # end
12 | # end
13 | describe CodingHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/spec/helpers/images_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the ImagesHelper. For example:
5 | #
6 | # describe ImagesHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # helper.concat_strings("this","that").should == "this that"
10 | # end
11 | # end
12 | # end
13 | describe ImagesHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/spec/helpers/thread_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the ThreadHelper. For example:
5 | #
6 | # describe ThreadHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # helper.concat_strings("this","that").should == "this that"
10 | # end
11 | # end
12 | # end
13 | describe ThreadHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | pageonex
4 |
5 |
6 |
7 |
8 |
9 | com.aptana.ide.core.unifiedBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.radrails.rails.core.railsnature
16 | com.aptana.ruby.core.rubynature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/spec/helpers/threads_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the ThreadsHelper. For example:
5 | #
6 | # describe ThreadsHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # helper.concat_strings("this","that").should == "this that"
10 | # end
11 | # end
12 | # end
13 | describe ThreadsHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/app/views/devise/confirmations/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Resend confirmation instructions - PageOneX" %>
2 | Resend confirmation instructions
3 |
4 | <%= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
5 | <%= devise_error_messages! %>
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email %>
9 |
10 | <%= f.submit "Resend confirmation instructions" %>
11 | <% end %>
12 |
13 | <%= render "links" %>
14 |
--------------------------------------------------------------------------------
/docker-compose-files/wrap-start-app.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # cleanup-pid-file-and-wait-for-mysql.sh
3 |
4 | set -e
5 |
6 | host="$1"
7 | password="$2"
8 | shift; shift
9 | cmd="$@"
10 |
11 | exec 2>&1
12 |
13 | rm -f /workspace/tmp/pids/server.pid
14 |
15 | port=${DATABASE_PORT:-3306}
16 |
17 | until mysql -u root --port $port --password=$password -h $host -e "SELECT 1"; do
18 | echo "Mysql is unavailable - sleeping"
19 | sleep 1
20 | done
21 |
22 | echo "Mysql is up - executing command"
23 | exec bash -c "$cmd"
24 |
--------------------------------------------------------------------------------
/config/locales/en.bootstrap.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | helpers:
6 | actions: "Actions"
7 | links:
8 | back: "Back"
9 | cancel: "Cancel"
10 | confirm: "Are you sure?"
11 | destroy: "Delete"
12 | new: "New"
13 | titles:
14 | edit: "Edit"
15 | save: "Save"
16 | new: "New"
17 | delete: "Delete"
18 |
--------------------------------------------------------------------------------
/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | Pageonex::Application.config.secret_token = '053292efff919bd0a5d02e4bfe0e0aaff33557d5101c0cdc79c4729c230d2258abf080ef4207f88fd0402db92917c0da67453237bef23776134cf349a328e465'
8 |
--------------------------------------------------------------------------------
/app/models/taxonomy_classification.rb:
--------------------------------------------------------------------------------
1 | class TaxonomyClassification < ActiveRecord::Base
2 | belongs_to :highlighted_area
3 | belongs_to :taxonomy_option
4 |
5 | delegate :taxonomy, to: :taxonomy_option
6 | delegate :code, to: :highlighted_area
7 |
8 | validate :taxonomy_in_thread
9 |
10 | def taxonomy_in_thread
11 | thread = Threadx.find(code.threadx_id)
12 | unless thread.taxonomy_ids.include?(taxonomy_option.taxonomy_id)
13 | errors.add(:taxonomy_option_id, 'Taxonomy not allowed in this thread')
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 | #
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # Disable root element in JSON by default.
12 | ActiveSupport.on_load(:active_record) do
13 | self.include_root_in_json = false
14 | end
15 |
--------------------------------------------------------------------------------
/app/models/area.rb:
--------------------------------------------------------------------------------
1 | class Area < ActiveRecord::Base
2 | belongs_to :highlighted_area
3 |
4 | # return a scaled down copy of the area
5 | def scaled_copy scale
6 | return Area.new(
7 | :x1=>(self.x1.to_f * scale).round,
8 | :x2=>(self.x2.to_f * scale).round,
9 | :y1=>(self.y1.to_f * scale).round,
10 | :y2=>(self.y2.to_f * scale).round,
11 | :width=>(self.width.to_f * scale).round,
12 | :height=>(self.height.to_f * scale).round,
13 | :highlighted_area_id=>self.highlighted_area_id,
14 | )
15 | end
16 |
17 | end
18 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/reset_password_instructions.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Reset password instructions- PageOneX" %>
2 | Hello <%= @resource.email %>!
3 |
4 | Someone has requested a link to change your password, and you can do this through the link below.
5 |
6 | <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>
7 |
8 | If you didn't request this, please ignore this email.
9 | Your password won't change until you access the link above and create a new one.
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: trusty
2 |
3 | language: ruby
4 |
5 | rvm:
6 | - 1.9.3-p551
7 |
8 | bundler_args: --without heroku
9 |
10 | sudo: required
11 |
12 | services:
13 | - mysql
14 |
15 | stages:
16 | - name: release
17 | if: tag IS present
18 |
19 | before_install:
20 | - sudo apt-get update
21 | - sudo apt-get install -y libxml2-dev
22 | - gem update --system
23 | - gem install --force bundler
24 | - gem install debugger-ruby_core_source
25 |
26 | jobs:
27 | include:
28 | - name: 'Push image to Docker Hub'
29 | stage: release
30 | script:
31 | - make docker-push
32 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery
3 | # the rails application does not accept big json request ,so to allow the user to submit a huge request to the server, we should configure rails to accept that, by setting the limit of the request to a huge number
4 | Rack::Utils.key_space_limit = 1000000000
5 |
6 | def use_local_images
7 | Pageonex::Application.config.use_local_images
8 | end
9 |
10 | def authenticate_admin!
11 | authenticate_user!
12 | redirect_to '/' unless current_user.admin
13 | end
14 |
15 | end
16 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format
4 | # (all these examples are active by default):
5 | # ActiveSupport::Inflector.inflections do |inflect|
6 | # inflect.plural /^(ox)$/i, '\1en'
7 | # inflect.singular /^(ox)en/i, '\1'
8 | # inflect.irregular 'person', 'people'
9 | # inflect.uncountable %w( fish sheep )
10 | # end
11 | #
12 | # These inflection rules are supported but not enabled by default:
13 | # ActiveSupport::Inflector.inflections do |inflect|
14 | # inflect.acronym 'RESTful'
15 | # end
16 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 | Threadx.create(thread_name: 'thread_social movement',thread_display_name: 'Social movement in front pages', start_date: '2013-02-01', end_date: '2013-02-15', description: 'the best description ever', category: 'social', status: 'closed', owner_id: '1')
9 |
10 |
--------------------------------------------------------------------------------
/docker-ruby/README.md:
--------------------------------------------------------------------------------
1 | # Pageonex Ruby base images
2 |
3 | Since we use old ruby versions, we need to build the images by ourselves compiling ruby from source. Once we're there, images will contain all the system dependencies that normally do not change so that main image builds only refer to the application
4 |
5 | Images will be uploaded to https://hub.docker.com/r/pageonex/ruby-base/tags/
6 |
7 | In order to build and push the ruby 1.9.3 image with its dependencies
8 |
9 | ```
10 | cd v1.9.3
11 | make docker-build
12 | make docker-push
13 | ```
14 |
15 | Image will be named `pageonex/ruby-base`:`v1.9.3.x` where `x` will be the revision in the `v1.9.3/REVISION` file
16 |
17 |
--------------------------------------------------------------------------------
/app/views/devise/passwords/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "User Change Password - PageOneX" %>
2 | Change your password
3 |
4 | <%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
5 | <%= devise_error_messages! %>
6 | <%= f.hidden_field :reset_password_token %>
7 |
8 | <%= f.label :password, "New password" %>
9 | <%= f.password_field :password %>
10 |
11 | <%= f.label :password_confirmation, "Confirm new password" %>
12 | <%= f.password_field :password_confirmation %>
13 |
14 | <%= f.submit "Change my password" %>
15 | <% end %>
16 |
17 | <%= render "links" %>
18 |
--------------------------------------------------------------------------------
/app/views/coding/_coding_footer.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/views/devise/sessions/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "User Sign in - PageOneX" %>
2 | Sign in
3 |
4 | <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
5 | <%= f.label :email %>
6 | <%= f.email_field :email %>
7 |
8 | <%= f.label :password %>
9 | <%= f.password_field :password %>
10 |
11 | <% if devise_mapping.rememberable? -%>
12 | <%= f.label :remember_me, :class => "checkbox" do %>
13 | <%= f.check_box :remember_me %>Remember me
14 | <% end %>
15 | <% end -%>
16 |
17 | <%= f.submit "Sign in",:class => "btn" %>
18 | <% end %>
19 |
20 | <%= render "links" %>
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/views/home/help.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Help - PageOneX" %>
2 |
3 |
Wiki
4 |
<%= link_to "Access the wiki", "https://github.com/numeroteca/pageonex/wiki" %>
5 |
How to use PageOneX
6 |
Tutorial about how to use PageOneX by Anibal Rossi (in Spanish). Thanks!
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-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 |
10 | # Ignore the default SQLite database.
11 | /db/*.sqlite3
12 |
13 | # Ignore all logfiles and tempfiles.
14 | /log/*.log
15 | /tmp
16 | *~
17 |
18 | /app/assets/images/kiosko
19 | /app/assets/images/threads
20 |
21 | # Ignore OS X image cache
22 | .DS_Store
23 |
24 | # ignore some generated thumb files
25 | app/assets/images/404-thumb*.jpg
26 |
--------------------------------------------------------------------------------
/app/views/devise/registrations/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "User sign up - PageOneX" %>
2 | Sign up
3 |
4 | <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
5 | <%= devise_error_messages! %>
6 |
7 | <%= f.label :username %>
8 | <%= f.text_field :username %>
9 |
10 | <%= f.label :email %>
11 | <%= f.email_field :email %>
12 |
13 | <%= f.label :password %>
14 | <%= f.password_field :password %>
15 |
16 | <%= f.label :password_confirmation %>
17 | <%= f.password_field :password_confirmation %>
18 |
19 | <%= f.submit "Sign up", :class => "btn" %>
20 | <% end %>
21 |
22 | <%= render "links" %>
23 |
--------------------------------------------------------------------------------
/app/views/taxonomies/new.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "New taxonomy - PageOneX" %>
2 |
5 | <%= form_for @taxonomy do |f| %>
6 |
7 | <%= f.label :name, class: "control-label" %>
8 |
9 | <%= f.text_field :name %>
10 |
11 |
12 | <% if @taxonomy.errors.messages[:name].present? %>
13 |
Error: <%= @taxonomy.errors.messages[:name].first %>
14 | <% end %>
15 |
16 |
17 |
18 |
19 | <%= f.submit "Create taxonomy", class: 'btn btn-primary' %>
20 | <%= link_to "Cancel", taxonomies_path, class: 'btn' %>
21 |
22 | <% end %>
23 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
We're sorry, but something went wrong.
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/models/highlighted_area.rb:
--------------------------------------------------------------------------------
1 | class HighlightedArea < ActiveRecord::Base
2 | has_many :areas
3 | has_many :taxonomy_classifications, dependent: :destroy
4 | has_many :taxonomy_options, through: :taxonomy_classifications
5 | belongs_to :code
6 | belongs_to :user
7 | belongs_to :image
8 |
9 | def threadx
10 | code.threadx unless code.nil?
11 | end
12 |
13 | def self.by_image(image)
14 | where(:image_id => image.id)
15 | end
16 |
17 | def self.by_threadx(threadx)
18 | where(:code_id => threadx.code_ids)
19 | end
20 |
21 | def self.by_code(code)
22 | where(:code_id => code.id)
23 | end
24 |
25 | def area
26 | areas.first.width * areas.first.height
27 | end
28 |
29 | def scaled_areas scale
30 | areas.collect { |a| a.scaled_copy scale }
31 | end
32 |
33 | end
34 |
--------------------------------------------------------------------------------
/spec/views/media/show.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "media/show" do
4 | before(:each) do
5 | @medium = assign(:medium, stub_model(Medium,
6 | :name => "Name",
7 | :country => "Country",
8 | :country_code => "Country Code",
9 | :url => "Url",
10 | :display_name => "Display Name",
11 | :working => false
12 | ))
13 | end
14 |
15 | it "renders attributes in " do
16 | render
17 | # Run the generator again with the --webrat flag if you want to use webrat matchers
18 | rendered.should match(/Name/)
19 | rendered.should match(/Country/)
20 | rendered.should match(/Country Code/)
21 | rendered.should match(/Url/)
22 | rendered.should match(/Display Name/)
23 | rendered.should match(/false/)
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/views/media/show.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Show Media - PageOneX" %>
2 |
<%= notice %>
3 |
4 | <%=@media.display_name%>
5 |
6 |
7 | See all the images for this media source
8 |
9 |
10 |
11 | Name:
12 | <%= @media.name %>
13 |
14 |
15 |
16 | Country:
17 | <%= @media.country %>
18 |
19 |
20 |
21 | Country code:
22 | <%= @media.country_code %>
23 |
24 |
25 |
26 | Url:
27 | <%= @media.url %>
28 |
29 |
30 |
31 | Display name:
32 | <%= @media.display_name %>
33 |
34 |
35 |
36 | Working:
37 | <%= @media.working %>
38 |
39 |
40 |
41 | <%= link_to 'Edit', edit_medium_path(@media) %> |
42 | <%= link_to 'Back', medium_path %>
43 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The change you wanted was rejected.
23 |
Maybe you tried to change something you didn't have access to.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/config/piwik.yml:
--------------------------------------------------------------------------------
1 | # Configuration:
2 | #
3 | # disabled
4 | # false if tracking tag should be shown
5 | # use_async
6 | # Set to true if you want to use asynchronous tracking
7 | # url
8 | # The url of your piwik instance (e.g. localhost/piwik/
9 | # id_site
10 | # The id of your website inside Piwik
11 | #
12 | production:
13 | piwik:
14 | id_site: <%= ENV['PIWIK_ID_SITE'].blank? ? '1' : ENV['PIWIK_ID_SITE'] %>
15 | url: <%= ENV['PIWIK_URL'].blank? ? 'piwik-production.example.com' : ENV['PIWIK_URL'] %>
16 | use_async: false
17 | disabled: false
18 |
19 | development:
20 | piwik:
21 | id_site: 1
22 | url: piwik-development.example.com
23 | disabled: true
24 | use_async: false
25 |
26 | test:
27 | piwik:
28 | id_site: 1
29 | url: localhost
30 | disabled: true
31 | use_async: false
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The page you were looking for doesn't exist.
23 |
You may have mistyped the address or the page may have moved.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/imgareaselect-css/imgareaselect-deprecated.css:
--------------------------------------------------------------------------------
1 | /*
2 | * imgAreaSelect style to be used with deprecated options
3 | */
4 |
5 | .imgareaselect-border1, .imgareaselect-border2,
6 | .imgareaselect-border3, .imgareaselect-border4 {
7 | filter: alpha(opacity=50);
8 | opacity: 0.5;
9 | }
10 |
11 | .imgareaselect-border1 {
12 | border: solid 1px #000;
13 | }
14 |
15 | .imgareaselect-border2 {
16 | border: dashed 1px #fff;
17 | }
18 |
19 | .imgareaselect-handle {
20 | background-color: #fff;
21 | border: solid 1px #000;
22 | filter: alpha(opacity=50);
23 | opacity: 0.5;
24 | }
25 |
26 | .imgareaselect-outer {
27 | background-color: #000;
28 | filter: alpha(opacity=40);
29 | opacity: 0.4;
30 | }
31 |
32 | .imgareaselect-selection {
33 | background-color: #fff;
34 | filter: alpha(opacity=0);
35 | opacity: 0;
36 | }
37 |
--------------------------------------------------------------------------------
/app/views/taxonomy_options/_form.html.erb:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/views/media/index.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "List media - PageOneX" %>
2 | Listing media
3 |
4 |
5 |
6 | Name
7 | Country
8 | Country code
9 | Url
10 | Display name
11 | Working
12 |
13 |
14 |
15 |
16 |
17 | <% @media_list.each do |media| %>
18 |
19 | <%= media.name %>
20 | <%= media.country %>
21 | <%= media.country_code %>
22 | <%= media.url %>
23 | <%= media.display_name %>
24 | <%= media.working %>
25 | <%= link_to 'Show', media %>
26 | <%= link_to 'Edit', edit_medium_path(media) %>
27 | <%= link_to 'Destroy', media, method: :delete, data: { confirm: 'Are you sure?' } %>
28 |
29 | <% end %>
30 |
31 |
32 |
33 |
34 | <%= link_to 'New Medium', new_medium_path %>
35 |
--------------------------------------------------------------------------------
/spec/routing/media_routing_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe MediaController do
4 | describe "routing" do
5 |
6 | it "routes to #index" do
7 | get("/media").should route_to("media#index")
8 | end
9 |
10 | it "routes to #new" do
11 | get("/media/new").should route_to("media#new")
12 | end
13 |
14 | it "routes to #show" do
15 | get("/media/1").should route_to("media#show", :id => "1")
16 | end
17 |
18 | it "routes to #edit" do
19 | get("/media/1/edit").should route_to("media#edit", :id => "1")
20 | end
21 |
22 | it "routes to #create" do
23 | post("/media").should route_to("media#create")
24 | end
25 |
26 | it "routes to #update" do
27 | put("/media/1").should route_to("media#update", :id => "1")
28 | end
29 |
30 | it "routes to #destroy" do
31 | delete("/media/1").should route_to("media#destroy", :id => "1")
32 | end
33 |
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/routing/users_routing_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe UsersController do
4 | describe "routing" do
5 |
6 | it "routes to #index" do
7 | get("/users").should route_to("users#index")
8 | end
9 |
10 | it "routes to #new" do
11 | get("/users/new").should route_to("users#new")
12 | end
13 |
14 | it "routes to #show" do
15 | get("/users/1").should route_to("users#show", :id => "1")
16 | end
17 |
18 | it "routes to #edit" do
19 | get("/users/1/edit").should route_to("users#edit", :id => "1")
20 | end
21 |
22 | it "routes to #create" do
23 | post("/users").should route_to("users#create")
24 | end
25 |
26 | it "routes to #update" do
27 | put("/users/1").should route_to("users#update", :id => "1")
28 | end
29 |
30 | it "routes to #destroy" do
31 | delete("/users/1").should route_to("users#destroy", :id => "1")
32 | end
33 |
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/routing/images_routing_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe ImagesController do
4 | describe "routing" do
5 |
6 | it "routes to #index" do
7 | get("/images").should route_to("images#index")
8 | end
9 |
10 | it "routes to #new" do
11 | get("/images/new").should route_to("images#new")
12 | end
13 |
14 | it "routes to #show" do
15 | get("/images/1").should route_to("images#show", :id => "1")
16 | end
17 |
18 | it "routes to #edit" do
19 | get("/images/1/edit").should route_to("images#edit", :id => "1")
20 | end
21 |
22 | it "routes to #create" do
23 | post("/images").should route_to("images#create")
24 | end
25 |
26 | it "routes to #update" do
27 | put("/images/1").should route_to("images#update", :id => "1")
28 | end
29 |
30 | it "routes to #destroy" do
31 | delete("/images/1").should route_to("images#destroy", :id => "1")
32 | end
33 |
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/app/views/users/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_for @user, :html => { :class => 'form-horizontal' } do |f| %>
2 |
3 | <%= f.label :username, :class => 'control-label' %>
4 |
5 | <%= f.text_field :username, :class => 'text_field' %>
6 |
7 |
8 |
9 | <%= f.label :email, :class => 'control-label' %>
10 |
11 | <%= f.text_field :email, :class => 'text_field' %>
12 |
13 |
14 |
15 | <%= f.label :admin, :class => 'control-label' %>
16 |
17 | <%= f.check_box :admin, :class => 'check_box' %>
18 |
19 |
20 |
21 |
22 | <%= f.submit nil, :class => 'btn btn-primary' %>
23 | <%= link_to t('.cancel', :default => t("helpers.links.cancel")),
24 | users_path, :class => 'btn' %>
25 |
26 | <% end %>
27 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/imgareaselect-css/imgareaselect-default.css:
--------------------------------------------------------------------------------
1 | /*
2 | * imgAreaSelect default style
3 | */
4 |
5 | .imgareaselect-border1 {
6 | background: url(border-v.gif) repeat-y left top;
7 | }
8 |
9 | .imgareaselect-border2 {
10 | background: url(border-h.gif) repeat-x left top;
11 | }
12 |
13 | .imgareaselect-border3 {
14 | background: url(border-v.gif) repeat-y right top;
15 | }
16 |
17 | .imgareaselect-border4 {
18 | background: url(border-h.gif) repeat-x left bottom;
19 | }
20 |
21 | .imgareaselect-border1, .imgareaselect-border2,
22 | .imgareaselect-border3, .imgareaselect-border4 {
23 | filter: alpha(opacity=50);
24 | opacity: 0.5;
25 | }
26 |
27 | .imgareaselect-handle {
28 | background-color: #fff;
29 | border: solid 1px #000;
30 | filter: alpha(opacity=50);
31 | opacity: 0.5;
32 | }
33 |
34 | .imgareaselect-outer {
35 | background-color: #000;
36 | filter: alpha(opacity=50);
37 | opacity: 0.5;
38 | }
39 |
40 | .imgareaselect-selection {
41 | }
--------------------------------------------------------------------------------
/app/assets/javascripts/topic_form.js:
--------------------------------------------------------------------------------
1 |
2 | $(function () {
3 |
4 | var initDelete = function () {
5 | $('.delete_topic').unbind('click');
6 | $('.delete_topic').click(function () {
7 | var index = $(this).attr('id').substr('delete_topic_'.length);
8 | $("#topic_deleted_" + index).val('1');
9 | $("#topic_" + index).hide();
10 | });
11 | }
12 |
13 | // lets you add new topics via Ajax request
14 | $('#add_topic').click(function() {
15 | var existingTopicCount = parseInt($("#topic_count").val());
16 | $.get('/threads/new_topic/'+existingTopicCount, function(data) {
17 | $('#topic-list').append(data);
18 | $("#topic_color_"+$("#topic_count").val()).minicolors({ defaultValue: '#FF0000' });
19 | $("#topic_count").val(existingTopicCount+1);
20 | initDelete();
21 | });
22 | });
23 | // add the first topic option dynamically if there are none
24 | if($("#topic_count").val()==0){
25 | $("#add_topic").click();
26 | }
27 | initDelete();
28 | });
29 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/imgareaselect-css/imgareaselect-animated.css:
--------------------------------------------------------------------------------
1 | /*
2 | * imgAreaSelect animated border style
3 | */
4 |
5 | .imgareaselect-border1 {
6 | background: url(border-anim-v.gif) repeat-y left top;
7 | }
8 |
9 | .imgareaselect-border2 {
10 | background: url(border-anim-h.gif) repeat-x left top;
11 | }
12 |
13 | .imgareaselect-border3 {
14 | background: url(border-anim-v.gif) repeat-y right top;
15 | }
16 |
17 | .imgareaselect-border4 {
18 | background: url(border-anim-h.gif) repeat-x left bottom;
19 | }
20 |
21 | .imgareaselect-border1, .imgareaselect-border2,
22 | .imgareaselect-border3, .imgareaselect-border4 {
23 | filter: alpha(opacity=50);
24 | opacity: 0.5;
25 | }
26 |
27 | .imgareaselect-handle {
28 | background-color: #fff;
29 | border: solid 1px #000;
30 | filter: alpha(opacity=50);
31 | opacity: 0.5;
32 | }
33 |
34 | .imgareaselect-outer {
35 | background-color: #000;
36 | filter: alpha(opacity=50);
37 | opacity: 0.5;
38 | }
39 |
40 | .imgareaselect-selection {
41 | }
--------------------------------------------------------------------------------
/app/assets/stylesheets/bootstrap_and_overrides.css.less:
--------------------------------------------------------------------------------
1 | @import "twitter/bootstrap/bootstrap";
2 | body { padding-top: 60px; }
3 |
4 | @import "twitter/bootstrap/responsive";
5 |
6 | // Set the correct sprite paths
7 | @iconSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings.png');
8 | @iconWhiteSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings-white.png');
9 |
10 | // Your custom LESS stylesheets goes here
11 | //
12 | // Since bootstrap was imported above you have access to its mixins which
13 | // you may use and inherit here
14 | //
15 | // If you'd like to override bootstrap's own variables, you can do so here as well
16 | // See http://twitter.github.com/bootstrap/less.html for their names and documentation
17 | //
18 | // Example:
19 | // @linkColor: #ff0000;
20 |
21 | .carousel-control{
22 | border: 3px solid #CCC;
23 | // left: -53px;
24 | // right: -53px !important;
25 | webkit-border-radius: 0px;
26 | -moz-border-radius: 0px;
27 | border-radius: 0px;
28 | -webkit-border-radius: 0px;
29 | -moz-border-radius: 0px;
30 | border-radius: 0px;
31 | top:300px;
32 | }
33 |
--------------------------------------------------------------------------------
/lib/tasks/scraping.rake:
--------------------------------------------------------------------------------
1 | require 'csv'
2 | require 'open-uri'
3 | require 'nokogiri'
4 | require 'kiosko_scraper'
5 |
6 | namespace :scraping do
7 |
8 | # rake scraping:scrape_media
9 | desc "Scrape Kiosko and generate a CSV of media sources"
10 | task :scrape_media => :environment do
11 | KioskoScraper::scrape_media_to_csv
12 | end
13 |
14 | # rake scraping:update_media
15 | desc "Import/update media into the database from a CSV of media sources"
16 | task :update_media => :environment do |t, args|
17 | KioskoScraper::update_media_from_csv
18 | end
19 |
20 | # rake scraping:scrape_day
21 | desc "Scrape images for the current day"
22 | task :scrape_day => :environment do
23 | day = Date.today - 1
24 | KioskoScraper::create_images(day, day, Media.all)
25 | end
26 |
27 | # rake scraping:migrate_media_folders_to_include_country_codes
28 | desc "One time-fix to migrate media folders to include country codes"
29 | task :migrate_media_folders_to_include_country_codes => :environment do
30 | KioskoScraper::migrate_media_folders_to_include_country_codes
31 | end
32 |
33 | end
34 |
--------------------------------------------------------------------------------
/spec/views/media/new.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "media/new" do
4 | before(:each) do
5 | assign(:medium, stub_model(Medium,
6 | :name => "MyString",
7 | :country => "MyString",
8 | :country_code => "MyString",
9 | :url => "MyString",
10 | :display_name => "MyString",
11 | :working => false
12 | ).as_new_record)
13 | end
14 |
15 | it "renders new medium form" do
16 | render
17 |
18 | # Run the generator again with the --webrat flag if you want to use webrat matchers
19 | assert_select "form[action=?][method=?]", media_path, "post" do
20 | assert_select "input#medium_name[name=?]", "medium[name]"
21 | assert_select "input#medium_country[name=?]", "medium[country]"
22 | assert_select "input#medium_country_code[name=?]", "medium[country_code]"
23 | assert_select "input#medium_url[name=?]", "medium[url]"
24 | assert_select "input#medium_display_name[name=?]", "medium[display_name]"
25 | assert_select "input#medium_working[name=?]", "medium[working]"
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/views/media/edit.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "media/edit" do
4 | before(:each) do
5 | @medium = assign(:medium, stub_model(Medium,
6 | :name => "MyString",
7 | :country => "MyString",
8 | :country_code => "MyString",
9 | :url => "MyString",
10 | :display_name => "MyString",
11 | :working => false
12 | ))
13 | end
14 |
15 | it "renders the edit medium form" do
16 | render
17 |
18 | # Run the generator again with the --webrat flag if you want to use webrat matchers
19 | assert_select "form[action=?][method=?]", medium_path(@medium), "post" do
20 | assert_select "input#medium_name[name=?]", "medium[name]"
21 | assert_select "input#medium_country[name=?]", "medium[country]"
22 | assert_select "input#medium_country_code[name=?]", "medium[country_code]"
23 | assert_select "input#medium_url[name=?]", "medium[url]"
24 | assert_select "input#medium_display_name[name=?]", "medium[display_name]"
25 | assert_select "input#medium_working[name=?]", "medium[working]"
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/app/models/media.rb:
--------------------------------------------------------------------------------
1 | class Media < ActiveRecord::Base
2 | has_many :images
3 | has_many :media_threadxes
4 | has_many :threadxes, :through => :media_threadxes
5 |
6 | default_scope where(:working=>true)
7 |
8 | scope :by_country_and_display_name, order("country, display_name")
9 |
10 | def name_with_country
11 | self.country + " - " + self.display_name
12 | end
13 |
14 | def image_directory_name
15 | self.country_code+"-"+self.name
16 | end
17 |
18 | def create_image_directory
19 | return false if not Pageonex::Application.config.use_local_images
20 | local_image_dir = File.join(KioskoScraper.local_image_dir, self.image_directory_name)
21 | FileUtils.mkdir local_image_dir unless File.directory? local_image_dir
22 | true
23 | end
24 |
25 | def self.from_csv_row row
26 | m = Media.new
27 | m.country = row[0]
28 | m.country_code = row[1]
29 | m.display_name = row[2]
30 | m.name = row[3]
31 | m.url = row[4]
32 | m
33 | end
34 |
35 | def to_csv_row
36 | [ self.country, self.country_code, self.display_name, self.name, self.url ]
37 | end
38 |
39 | end
40 |
--------------------------------------------------------------------------------
/app/controllers/taxonomies_controller.rb:
--------------------------------------------------------------------------------
1 | class TaxonomiesController < ApplicationController
2 |
3 | before_filter :authenticate_admin!
4 |
5 | def index
6 | @taxonomies = Taxonomy.includes(:taxonomy_options).all
7 | end
8 |
9 | def new
10 | @taxonomy = Taxonomy.new
11 | end
12 |
13 | def edit
14 | @taxonomies = Taxonomy.includes(:taxonomy_options).all
15 | @taxonomy = Taxonomy.find(params[:id])
16 | end
17 |
18 | def create
19 | @taxonomy = Taxonomy.new(params[:taxonomy])
20 |
21 | if @taxonomy.save
22 | redirect_to taxonomy_taxonomy_options_url(@taxonomy.id), notice: 'Taxonomy was successfully created.'
23 | else
24 | render action: "new"
25 | end
26 | end
27 |
28 | def update
29 | @taxonomy = Taxonomy.find(params[:id])
30 |
31 | if @taxonomy.update_attributes(params[:taxonomy])
32 | redirect_to taxonomies_url
33 | else
34 | @taxonomies = Taxonomy.includes(:taxonomy_options).all
35 | render action: "edit"
36 | end
37 | end
38 |
39 | def destroy
40 | @taxonomy = Taxonomy.find(params[:id])
41 | @taxonomy.destroy
42 |
43 | redirect_to taxonomies_url
44 | end
45 | end
--------------------------------------------------------------------------------
/app/views/media/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_for(@media) do |f| %>
2 | <% if @media.errors.any? %>
3 |
4 |
<%= pluralize(@media.errors.count, "error") %> prohibited this media from being saved:
5 |
6 |
7 | <% @media.errors.full_messages.each do |msg| %>
8 | <%= msg %>
9 | <% end %>
10 |
11 |
12 | <% end %>
13 |
14 |
15 | <%= f.label :name %>
16 | <%= f.text_field :name %>
17 |
18 |
19 | <%= f.label :country %>
20 | <%= f.text_field :country %>
21 |
22 |
23 | <%= f.label :country_code %>
24 | <%= f.text_field :country_code %>
25 |
26 |
27 | <%= f.label :url %>
28 | <%= f.text_field :url %>
29 |
30 |
31 | <%= f.label :display_name %>
32 | <%= f.text_field :display_name %>
33 |
34 |
35 | <%= f.label :working %>
36 | <%= f.check_box :working %>
37 |
38 |
39 | <%= f.submit %>
40 |
41 | <% end %>
42 |
--------------------------------------------------------------------------------
/app/views/devise/_links.erb:
--------------------------------------------------------------------------------
1 | <%- if controller_name != 'sessions' %>
2 | <%= link_to "Sign in", new_session_path(resource_name) %>
3 | <% end -%>
4 |
5 | <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
6 | <%= link_to "Sign up", new_registration_path(resource_name) %>
7 | <% end -%>
8 |
9 | <%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
10 | <%= link_to "Forgot your password?", new_password_path(resource_name) %>
11 | <% end -%>
12 |
13 | <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
14 | <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
15 | <% end -%>
16 |
17 | <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18 | <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
19 | <% end -%>
20 |
21 | <%- if devise_mapping.omniauthable? %>
22 | <%- resource_class.omniauth_providers.each do |provider| %>
23 | <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %>
24 | <% end -%>
25 | <% end -%>
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PROJECT = pageonex
2 | DOCKER_REGISTRY ?= docker.io
3 | DOCKER_ORG ?= pageonex
4 | DOCKER_USERNAME ?=
5 | DOCKER_PASSWORD ?=
6 | VERSION ?= $(TRAVIS_TAG)
7 |
8 | docker-login: docker-validate
9 | @docker login -u "$(DOCKER_USERNAME)" -p "$(DOCKER_PASSWORD)" $(DOCKER_REGISTRY); \
10 |
11 | docker-validate:
12 | @if [ -z "$(DOCKER_USERNAME)" ]; then \
13 | echo "DOCKER_USERNAME variable cannot be empty."; \
14 | exit 1; \
15 | fi; \
16 | if [ -z "$(DOCKER_PASSWORD)" ]; then \
17 | echo "DOCKER_PASSWORD variable cannot be empty."; \
18 | exit 1; \
19 | fi
20 |
21 | docker-build:
22 | @if [ -z "$(VERSION)" ]; then \
23 | echo "VERSION variable cannot be empty."; \
24 | exit 1; \
25 | fi; \
26 | if [ -z "$(DOCKER_ORG)" ]; then \
27 | echo "DOCKER_ORG variable cannot be empty."; \
28 | exit 1; \
29 | fi; \
30 | docker build -t $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT):$(VERSION) .; \
31 |
32 | docker-push: docker-login docker-build
33 | docker push $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT):$(VERSION); \
34 | docker tag $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT):$(VERSION) \
35 | $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT):latest; \
36 | docker push $(DOCKER_REGISTRY)/$(DOCKER_ORG)/$(PROJECT):latest;
37 |
--------------------------------------------------------------------------------
/spec/views/media/index.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "media/index" do
4 | before(:each) do
5 | assign(:media, [
6 | stub_model(Medium,
7 | :name => "Name",
8 | :country => "Country",
9 | :country_code => "Country Code",
10 | :url => "Url",
11 | :display_name => "Display Name",
12 | :working => false
13 | ),
14 | stub_model(Medium,
15 | :name => "Name",
16 | :country => "Country",
17 | :country_code => "Country Code",
18 | :url => "Url",
19 | :display_name => "Display Name",
20 | :working => false
21 | )
22 | ])
23 | end
24 |
25 | it "renders a list of media" do
26 | render
27 | # Run the generator again with the --webrat flag if you want to use webrat matchers
28 | assert_select "tr>td", :text => "Name".to_s, :count => 2
29 | assert_select "tr>td", :text => "Country".to_s, :count => 2
30 | assert_select "tr>td", :text => "Country Code".to_s, :count => 2
31 | assert_select "tr>td", :text => "Url".to_s, :count => 2
32 | assert_select "tr>td", :text => "Display Name".to_s, :count => 2
33 | assert_select "tr>td", :text => false.to_s, :count => 2
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/docker-compose-build.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | volumes:
3 | build_db_data:
4 |
5 | services:
6 | mysql_build:
7 | image: mysql:5.6.40
8 | restart: always
9 | ports:
10 | - "23306:23306"
11 | volumes:
12 | - build_db_data:/var/lib/mysql
13 | - ./docker-compose-files/pageonex-build.cnf:/etc/mysql/conf.d/pageonex-build.cnf
14 | environment:
15 | - MYSQL_ROOT_PASSWORD=root
16 | - MYSQL_DATABASE=dc-dev
17 | command: |
18 | bash -c "chmod 644 /etc/mysql/conf.d/pageonex-build.cnf && /entrypoint.sh mysqld"
19 |
20 | app_build:
21 | build: .
22 | environment:
23 | - RAILS_ENV=development
24 | - DATABASE_ADAPTER=mysql2
25 | - DATABASE_USERNAME=root
26 | - DATABASE_PASSWORD=root
27 | - DATABASE_HOST=mysql_build
28 | - DATABASE_PORT=23306
29 | - DATABASE_NAME=dc-dev
30 | depends_on:
31 | - "mysql_build"
32 | ports:
33 | - '3000:3000'
34 | links:
35 | - "mysql_build"
36 | volumes:
37 | - .:/workspace
38 | - ./docker-compose-files/wrap-start-app.sh:/usr/local/bin/wrap-start-app.sh
39 | working_dir: /workspace
40 | command:
41 | - wrap-start-app.sh
42 | - mysql_build
43 | - root
44 | - "bundle exec puma -C config/puma.rb"
45 |
--------------------------------------------------------------------------------
/docker-ruby/v1.9.3/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:jessie-slim
2 |
3 | ENV RUBY_VERSION 1.9.3-p551
4 | ENV RUBY_SHA1SUM 5cf6c9383444163a3f753b50c35e441988189258
5 |
6 | RUN BUILD_DIR="/tmp/ruby-build" \
7 | && apt-get update \
8 | && apt-get -y install \
9 | wget \
10 | build-essential \
11 | zlib1g-dev \
12 | libssl-dev \
13 | libreadline6-dev \
14 | libyaml-dev \
15 | tzdata \
16 | libmysqlclient-dev \
17 | mysql-client \
18 | libpq-dev \
19 | libxml2-dev \
20 | libxslt1-dev \
21 | nodejs \
22 | libmagickwand-dev \
23 | libsqlite3-dev \
24 | && mkdir -p "$BUILD_DIR" \
25 | && cd "$BUILD_DIR" \
26 | && wget -q "http://cache.ruby-lang.org/pub/ruby/ruby-${RUBY_VERSION}.tar.gz" \
27 | && echo "${RUBY_SHA1SUM} ruby-${RUBY_VERSION}.tar.gz" | sha1sum -c - \
28 | && tar xzf "ruby-${RUBY_VERSION}.tar.gz" \
29 | && cd "ruby-${RUBY_VERSION}" \
30 | && ./configure --enable-shared --prefix=/usr \
31 | && make \
32 | && make install \
33 | && cd / \
34 | && rm -r "$BUILD_DIR" \
35 | && rm -rf /var/lib/apt/lists/*
36 |
37 | RUN gem update --system \
38 | && gem install --force bundler \
39 | && gem install debugger-ruby_core_source
40 |
--------------------------------------------------------------------------------
/app/assets/javascripts/collaborators.js:
--------------------------------------------------------------------------------
1 | var Collaborators = {
2 | init: function () {
3 | if (!Collaborators.initialized) {
4 | Collaborators.list = $('#collab-list');
5 | Collaborators.inputContainer = $('#collab-inputs');
6 | Collaborators.userToLi = {}
7 | Collaborators.userToInput = {}
8 | }
9 | Collaborators.initialized = true;
10 | },
11 | add: function (username, hash) {
12 | Collaborators.init();
13 | if (typeof(Collaborators.userToLi[username]) != 'undefined') {
14 | return;
15 | }
16 | var li = $(' ' + username + ' (remove ) ');
17 | li.appendTo(this.list);
18 | Collaborators.userToLi[username] = li;
19 | var input = $(' ');
20 | Collaborators.userToInput[username] = input;
21 | input.appendTo(this.inputContainer);
22 | },
23 | remove: function (username) {
24 | Collaborators.init();
25 | Collaborators.userToLi[username].remove();
26 | Collaborators.userToInput[username].remove();
27 | delete Collaborators.userToLi[username];
28 | delete Collaborators.userToInput[username];
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | default: &default
2 | adapter: <%= ENV['DATABASE_ADAPTER'].blank? ? 'sqlite3' : ENV['DATABASE_ADAPTER'] %>
3 | encoding: <%= ENV['DATABASE_ENCODING'].blank? ? 'utf8' : ENV['DATABASE_ENCODING'] %>
4 | pool: <%= ENV['DATABASE_POOL'].blank? ? 5 : ENV['DATABASE_POOL'].to_i %>
5 | timeout: <%= ENV['DATABASE_TIMEOUT'].blank? ? 5000 : ENV['DATABASE_TIMEOUT'].to_i %>
6 | username: <%= ENV['DATABASE_USERNAME'].blank? ? 'root' : ENV['DATABASE_USERNAME'] %>
7 | password: <%= ENV['DATABASE_PASSWORD'].blank? ? 'root' : ENV['DATABASE_PASSWORD'] %>
8 | host: <%= ENV['DATABASE_HOST'].blank? ? 'localhost' : ENV['DATABASE_HOST'] %>
9 | port: <%= ENV['DATABASE_PORT'].blank? ? 3306 : ENV['DATABASE_PORT'].to_i %>
10 |
11 | development:
12 | <<: *default
13 | database: <%= ENV['DATABASE_NAME'].blank? ? 'db/development.sqlite3' : ENV['DATABASE_NAME'] %>
14 |
15 | # Warning: The database defined as "test" will be erased and
16 | # re-generated from your development database when you run "rake".
17 | # Do not set this db to the same as development or production.
18 | test:
19 | <<: *default
20 | database: <%= ENV['DATABASE_NAME'].blank? ? 'db/test.sqlite3' : ENV['DATABASE_NAME'] %>
21 |
22 | production:
23 | <<: *default
24 | database: <%= ENV['DATABASE_NAME'].blank? ? 'db/production.sqlite3' : ENV['DATABASE_NAME'] %>
25 |
--------------------------------------------------------------------------------
/app/views/devise/registrations/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "User registration edit- PageOneX" %>
2 | Edit <%= resource_name.to_s.humanize %>
3 |
4 | <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
5 | <%= devise_error_messages! %>
6 |
7 | <%= f.label :username %>
8 | <%= f.text_field :username %>
9 |
10 | <%= f.label :bio %>
11 | <%= f.text_area :bio, rows: 5, :rel=>"popover", 'data-content'=>"Allowed HTML tags:
..." %>
12 |
13 | <%= f.label :email %>
14 | <%= f.email_field :email %>
15 |
16 | <%= f.label :password %>
17 | <%= f.password_field :password, :autocomplete => "off" %> (leave blank if you don't want to change it)
18 |
19 | <%= f.label :password_confirmation %>
20 | <%= f.password_field :password_confirmation %>
21 |
22 | <%= f.label :current_password %>
23 | <%= f.password_field :current_password %> (we need your current password to confirm your changes)
24 |
25 | <%= f.submit "Update", :class => "btn" %>
26 | <% end %>
27 |
28 | Cancel my account
29 |
30 | Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.
31 |
32 | <%= link_to "Back", :back %>
33 |
--------------------------------------------------------------------------------
/app/views/taxonomy_options/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Taxonomy: #{@taxonomy.name} - PageOneX" %>
2 |
5 |
6 | <%= form_for [@taxonomy, @taxonomy_option] do |f| %>
7 |
8 |
9 |
10 | Option Id
11 | Value
12 | Actions
13 |
14 |
15 |
16 | <% @taxonomy_options.each do |option| %>
17 |
18 | <%= option.id %>
19 | <% if option == @taxonomy_option %>
20 |
21 | <%= f.text_field :value, class: 'input-medium' %>
22 | <% if @taxonomy_option.errors.messages[:value].present? %>
23 | Error: <%= @taxonomy_option.errors.messages[:value].first %>
24 | <% end %>
25 |
26 |
27 | <%= f.submit "Change value", class: 'btn btn-primary btn-mini' %>
28 | <%= link_to "Cancel", taxonomy_taxonomy_options_path(@taxonomy), class: 'btn btn-mini' %>
29 |
30 | <% else %>
31 | <%= option.value %>
32 |
33 | <% end %>
34 |
35 | <% end %>
36 |
37 |
38 | <% end %>
39 |
--------------------------------------------------------------------------------
/app/views/taxonomies/index.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Taxonomies list - PageOneX" %>
2 |
5 |
6 | <% if @taxonomies.present? %>
7 |
8 |
9 |
10 | Id
11 | Name
12 | Options
13 | Actions
14 |
15 |
16 |
17 | <% @taxonomies.each do |taxonomy| %>
18 |
19 | <%= link_to taxonomy.id, taxonomy_taxonomy_options_path(taxonomy) %>
20 | <%= link_to taxonomy.name, taxonomy_taxonomy_options_path(taxonomy) %>
21 | <%= link_to taxonomy.taxonomy_options.map(&:value)*' | ', taxonomy_taxonomy_options_path(taxonomy) %>
22 |
23 | <%= link_to "Change name", edit_taxonomy_path(taxonomy), class: 'btn btn-mini' %>
24 | <%= link_to "Destroy", taxonomy_path(taxonomy),
25 | method: :delete,
26 | data: { confirm: 'Are you sure?' },
27 | class: 'btn btn-mini btn-danger' %>
28 |
29 |
30 | <% end %>
31 |
32 |
33 |
34 | <%= link_to "New", new_taxonomy_path, class: 'btn btn-primary' %>
35 | <% else %>
36 | There are not taxonomies yet
37 | <%= link_to "Create the first one", new_taxonomy_path, class: 'btn btn-primary' %>
38 | <% end %>
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | require 'digest/md5'
2 |
3 | class User < ActiveRecord::Base
4 | # Include default devise modules. Others available are:
5 | # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
6 | devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
7 |
8 | # Setup accessible (or protected) attributes for your model
9 | attr_accessible :username, :email, :password, :password_confirmation, :remember_me, :bio
10 |
11 | has_many :highlighted_areas
12 |
13 | has_many :owned_threads, :class_name => "Threadx",:foreign_key => :owner_id
14 |
15 | has_many :threadx_collaborators
16 | has_many :coll_threads, :through => :threadx_collaborators, :source => :threadx
17 |
18 | validates_uniqueness_of :username
19 | validate :ok_username
20 |
21 | # we want to prevent users from creating certain usernames
22 | def ok_username
23 | if ['pageonex', 'admin', 'user', 'thread', 'example', 'blog', 'timeline', 'documentation', 'wiki', 'about', 'frontpage'].include? self.username
24 | errors.add(:userame, "isn't valid")
25 | end
26 | end
27 |
28 | def email_hash
29 | return Digest::MD5.hexdigest(self.email.downcase)
30 | end
31 |
32 | def self.hashes
33 | emails = User.select("username, email").all
34 | result = {}
35 | hashes = emails.map do |u|
36 | digest = Digest::MD5.hexdigest(u['email'].downcase)
37 | result[u['username']] = digest
38 | end
39 | return result
40 | end
41 |
42 | end
43 |
--------------------------------------------------------------------------------
/app/controllers/taxonomy_options_controller.rb:
--------------------------------------------------------------------------------
1 | class TaxonomyOptionsController < ApplicationController
2 |
3 | before_filter :authenticate_admin!
4 |
5 | before_filter :load_taxonomy, only: [:index, :destroy, :create, :edit, :update]
6 | before_filter :load_taxonomy_option, only: [:destroy, :edit, :update]
7 | before_filter :load_taxonomy_options, only: [:index, :edit]
8 |
9 | def index
10 | end
11 |
12 | def edit
13 | end
14 |
15 | def create
16 | @taxonomy_option = @taxonomy.taxonomy_options.new(params[:taxonomy_option])
17 |
18 | if @taxonomy_option.save
19 | redirect_to taxonomy_taxonomy_options_url(@taxonomy)
20 | else
21 | redirect_to taxonomy_taxonomy_options_url(@taxonomy), alert: "Error: #{@taxonomy_option.errors[:value].first}"
22 | end
23 | end
24 |
25 | def update
26 | if @taxonomy_option.update_attributes(params[:taxonomy_option])
27 | redirect_to taxonomy_taxonomy_options_url(@taxonomy)
28 | else
29 | load_taxonomy_options
30 | render action: "edit"
31 | end
32 | end
33 |
34 | def destroy
35 | @taxonomy_option.destroy
36 |
37 | redirect_to taxonomy_taxonomy_options_url(@taxonomy)
38 | end
39 |
40 | private
41 | def load_taxonomy
42 | @taxonomy = Taxonomy.find(params[:taxonomy_id])
43 | end
44 |
45 | def load_taxonomy_option
46 | @taxonomy_option = @taxonomy.taxonomy_options.find(params[:id])
47 | end
48 |
49 | def load_taxonomy_options
50 | @taxonomy_options = @taxonomy.taxonomy_options
51 | end
52 | end
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | volumes:
3 | db_data:
4 | app_kiosko_images:
5 | app_threads_images:
6 | app_tmp_dir:
7 |
8 | services:
9 | mysql:
10 | image: "mysql:5.6.40"
11 | restart: always
12 | ports:
13 | - "13306:13306"
14 | volumes:
15 | - db_data:/var/lib/mysql
16 | - ./docker-compose-files/pageonex.cnf:/etc/mysql/conf.d/pageonex.cnf
17 | environment:
18 | - MYSQL_ROOT_PASSWORD=root
19 | - MYSQL_DATABASE=dc-prod
20 | command: |
21 | bash -c "chmod 644 /etc/mysql/conf.d/pageonex.cnf && /entrypoint.sh mysqld"
22 |
23 | app:
24 | image: pageonex/pageonex:latest
25 | environment:
26 | - RAILS_ENV=production
27 | - DATABASE_ADAPTER=mysql2
28 | - DATABASE_USERNAME=root
29 | - DATABASE_PASSWORD=root
30 | - DATABASE_HOST=mysql
31 | - DATABASE_PORT=13306
32 | - DATABASE_NAME=dc-prod
33 | depends_on:
34 | - "mysql"
35 | ports:
36 | - '3000:3000'
37 | links:
38 | - "mysql"
39 | volumes:
40 | - app_tmp_dir:/workspace/tmp
41 | - app_kiosko_images:/workspace/app/assets/images/kiosko
42 | - app_threads_images:/workspace/app/assets/images/threads
43 | - ./docker-compose-files/wrap-start-app.sh:/usr/local/bin/wrap-start-app.sh
44 | command:
45 | - wrap-start-app.sh
46 | - mysql
47 | - root
48 | - "bundle exec rake db:migrate --trace && bundle exec rake scraping:update_media && bundle exec rake assets:precompile --trace && bundle exec puma -C config/puma.rb"
49 |
--------------------------------------------------------------------------------
/app/views/taxonomies/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Taxonomies list - PageOneX" %>
2 |
5 |
6 | <%= form_for @taxonomy do |f| %>
7 |
8 |
9 |
10 | Id
11 | Name
12 | Options
13 | Actions
14 |
15 |
16 |
17 | <% @taxonomies.each do |taxonomy| %>
18 | <% if taxonomy == @taxonomy %>
19 |
20 | <%= link_to taxonomy.id, taxonomy_taxonomy_options_path(taxonomy) %>
21 |
22 | <%= f.text_field :name, class: 'input-medium' %>
23 | <% if @taxonomy.errors.messages[:name].present? %>
24 | Error: <%= @taxonomy.errors.messages[:name].first %>
25 | <% end %>
26 |
27 | <%= link_to taxonomy.taxonomy_options.map(&:value)*' | ', taxonomy_taxonomy_options_path(taxonomy) %>
28 |
29 | <%= f.submit "Change name", class: 'btn btn-primary btn-mini' %>
30 | <%= link_to "Cancel", taxonomies_path, class: 'btn btn-mini' %>
31 |
32 |
33 |
34 | <% else %>
35 |
36 | <%= taxonomy.id %>
37 | <%= taxonomy.name %>
38 | <%= taxonomy.taxonomy_options.map(&:value)*' | ' %>
39 |
40 |
41 | <% end %>
42 | <% end %>
43 |
44 |
45 | <% end %>
46 |
--------------------------------------------------------------------------------
/app/views/images/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_for @image, :html => { :class => 'form-horizontal' } do |f| %>
2 |
3 | <%= f.label :publication_date, :class => 'control-label' %>
4 |
5 | <%= f.date_select :publication_date, :class => 'date_select' %>
6 |
7 |
8 |
9 | <%= f.label :size, :class => 'control-label' %>
10 |
11 | <%= f.text_field :size, :class => 'text_field' %>
12 |
13 |
14 |
15 | <%= f.label :media_id, :class => 'control-label' %>
16 |
17 | <%= f.number_field :media_id, :class => 'number_field' %>
18 |
19 |
20 |
21 | <%= f.label :image_name, :class => 'control-label' %>
22 |
23 | <%= f.text_field :image_name, :class => 'text_field' %>
24 |
25 |
26 |
27 | <%= f.label :source_url, :class => 'control-label' %>
28 |
29 | <%= f.text_field :source_url, :class => 'text_field' %>
30 |
31 |
32 |
33 | <%= f.label :missing, :class => 'control-label' %>
34 |
35 | <%= f.check_box :missing, :class => 'check_box' %>
36 |
37 |
38 |
39 |
40 | <%= f.submit nil, :class => 'btn btn-primary' %>
41 | <%= link_to t('.cancel', :default => t("helpers.links.cancel")),
42 | images_path, :class => 'btn' %>
43 |
44 | <% end %>
45 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Pageonex::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Configure static asset server for tests with Cache-Control for performance
11 | config.serve_static_assets = true
12 | config.static_cache_control = "public, max-age=3600"
13 |
14 | # Log error messages when you accidentally call methods on nil
15 | config.whiny_nils = true
16 |
17 | # Show full error reports and disable caching
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Raise exception on mass assignment protection for Active Record models
33 | config.active_record.mass_assignment_sanitizer = :strict
34 |
35 | # Print deprecation notices to the stderr
36 | config.active_support.deprecation = :stderr
37 | end
38 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # specify a ruby version! (rvm respects this)
4 | ruby "1.9.3"
5 |
6 | gem 'rails', '3.2.13'
7 |
8 | # HACK: this group holds gems we need for heroku
9 | group :heroku do
10 | gem 'pg'
11 | end
12 |
13 | # Gems used only for assets and not required
14 | # in production environments by default.
15 | group :assets do
16 | gem 'sass-rails', '~> 3.2.3'
17 | gem 'coffee-rails', '~> 3.2.1'
18 | gem 'uglifier', '>= 1.0.3'
19 | end
20 |
21 | # GUI support libraries
22 | gem 'therubyracer', '~> 0.12.3' # See https://github.com/sstephenson/execjs#readme for more supported runtimes
23 | gem 'less-rails'
24 | gem "twitter-bootstrap-rails"
25 | gem "jquery-rails"
26 | gem "jquery-ui-rails"
27 |
28 | group :development, :test do
29 | gem 'sqlite3'
30 | gem 'rspec-rails'
31 | gem 'factory_girl_rails'
32 | gem 'debugger'
33 | end
34 |
35 | group :test do
36 | gem 'faker'
37 | gem 'capybara'
38 | gem 'guard-rspec'
39 | gem 'launchy'
40 | end
41 |
42 | gem 'mysql2', '~> 0.3.21'
43 |
44 | # ODF generation for exporting results
45 | gem 'rodf'
46 |
47 | # save image size while scraping kiosko.net
48 | gem "imagesize"
49 |
50 | # for thumbnails, because integrating paperclip gem at this point is too hard
51 | gem 'rmagick'
52 |
53 | # full management of user accounts
54 | gem 'devise'
55 |
56 | # smart generation of slugs for theadx objects
57 | gem 'stringex'
58 |
59 | # pagination support
60 | gem 'will_paginate', '~> 3.0'
61 | gem 'bootstrap-will_paginate'
62 |
63 | # web analytics
64 | gem 'piwik_analytics'
65 |
66 | # for downloading zipped archives
67 | gem 'rubyzip'
68 |
69 | gem 'puma', '~> 3.11.4'
70 | gem 'puma_worker_killer'
71 |
--------------------------------------------------------------------------------
/doc/docker/running-pageonex-in-your-environment.md:
--------------------------------------------------------------------------------
1 | # Runining pageonex in your environment
2 |
3 | If you want to create your own deployment of pageonex, the easiest way to do it is to use one of our [docker images](https://hub.docker.com/r/pageonex/pageonex/tags) and connect it to the database. These are the main configuration areas:
4 |
5 | ## Rails environment configuration
6 |
7 | You need to set the `RAILS_ENV` to `production`
8 |
9 | ## Database access configuration
10 |
11 | Pageonex has been mainly tested with mysql, so this is our recommendation. Due to [this issue](https://github.com/montera34/pageonex/issues/212), mysql <= 5.6 is required
12 |
13 | There are a few env variables that should be set to customize your database access:
14 |
15 | * `DATABASE_ADAPTER`: This should be set to `mysql2`
16 | * `DATABASE_USERNAME`: The database user to accesss
17 | * `DATABASE_PASSWORD`: The password corresponding to above user
18 | * `DATABASE_HOST`: Database address
19 | * `DATABASE_PORT`: Database port
20 | * `DATABASE_NAME`: Database name in above host:port
21 |
22 | See [database.yml](/config/database.yml) for more settings and default values.
23 |
24 | ## Filesystem mounts
25 |
26 | There are a few mount points to be set in order to avoid writes in the container filesystem which would lead to data loss and performance degradation:
27 |
28 | * kiosko images: `/workspace/app/assets/images/kiosko`
29 | * threads images: `/workspace/app/assets/images/threads`
30 | * temp files: `/workspace/tmp`
31 |
32 | ## Rake tasks
33 |
34 | These should be run on deployment:
35 |
36 | * Database schema creation/modification: `db:migrate`
37 | * Media list: `scraping:update_media`
38 | * Assets precompilation: `bundle exec rake assets:precompile`
39 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Pageonex::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | config.action_mailer.delivery_method = :sendmail
17 | config.action_mailer.perform_deliveries = true
18 |
19 | # Don't care if the mailer can't send
20 | config.action_mailer.raise_delivery_errors = true
21 |
22 | config.action_mailer.default_url_options = { :host => 'localhost:3000' }
23 |
24 | # Print deprecation notices to the Rails logger
25 | config.active_support.deprecation = :log
26 |
27 | # Only use best-standards-support built into browsers
28 | config.action_dispatch.best_standards_support = :builtin
29 |
30 | # Raise exception on mass assignment protection for Active Record models
31 | config.active_record.mass_assignment_sanitizer = :strict
32 |
33 | # Log the query plan for queries taking more than this (works
34 | # with SQLite, MySQL, and PostgreSQL)
35 | config.active_record.auto_explain_threshold_in_seconds = 0.5
36 |
37 | # Do not compress assets
38 | config.assets.compress = false
39 |
40 | # Expands the lines which load the assets
41 | config.assets.debug = true
42 |
43 | end
44 |
--------------------------------------------------------------------------------
/db/migrate/20120627130452_devise_create_users.rb:
--------------------------------------------------------------------------------
1 | class DeviseCreateUsers < ActiveRecord::Migration
2 | def change
3 | create_table(:users) do |t|
4 | ## Database authenticatable
5 | t.string :username, :null => false, :default => ""
6 | t.string :email, :null => false, :default => ""
7 | t.string :encrypted_password, :null => false, :default => ""
8 |
9 | ## Recoverable
10 | t.string :reset_password_token
11 | t.datetime :reset_password_sent_at
12 |
13 | ## Rememberable
14 | t.datetime :remember_created_at
15 |
16 | ## Trackable
17 | t.integer :sign_in_count, :default => 0
18 | t.datetime :current_sign_in_at
19 | t.datetime :last_sign_in_at
20 | t.string :current_sign_in_ip
21 | t.string :last_sign_in_ip
22 |
23 | ## Encryptable
24 | # t.string :password_salt
25 |
26 | ## Confirmable
27 | # t.string :confirmation_token
28 | # t.datetime :confirmed_at
29 | # t.datetime :confirmation_sent_at
30 | # t.string :unconfirmed_email # Only if using reconfirmable
31 |
32 | ## Lockable
33 | # t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
34 | # t.string :unlock_token # Only if unlock strategy is :email or :both
35 | # t.datetime :locked_at
36 |
37 | ## Token authenticatable
38 | # t.string :authentication_token
39 |
40 |
41 | t.timestamps
42 | end
43 |
44 | add_index :users, :email, :unique => true
45 | add_index :users, :reset_password_token, :unique => true
46 | # add_index :users, :confirmation_token, :unique => true
47 | # add_index :users, :unlock_token, :unique => true
48 | # add_index :users, :authentication_token, :unique => true
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/app/views/taxonomy_options/index.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Taxonomy: #{@taxonomy.name} - PageOneX" %>
2 |
5 |
6 | <% if @taxonomy_options.present? %>
7 |
8 |
9 |
10 | Option Id
11 | Value
12 | Actions
13 |
14 |
15 |
16 | <% @taxonomy_options.each do |option| %>
17 |
18 | <%= option.id %>
19 | <%= option.value %>
20 |
21 | <%= link_to "Change value", edit_taxonomy_taxonomy_option_path(@taxonomy, option), class: 'btn btn-mini' %>
22 | <%= link_to 'Destroy', taxonomy_taxonomy_option_path(@taxonomy.id, option.id),
23 | method: :delete,
24 | data: { confirm: 'Are you sure?' },
25 | class: 'btn btn-mini btn-danger' %>
26 |
27 |
28 | <% end %>
29 |
30 |
31 | <% end %>
32 |
33 | <%= render partial: 'form' %>
34 |
35 |
36 | <% if @taxonomy_options.present? %>
37 | <%= content_tag :span, 'Add new option', class: 'btn btn-primary js-toggle-elements',
38 | data: { show: 'taxonomy-option-create-form', hide: 'taxonomy-options-admin-add' } %>
39 | <% else %>
40 |
41 | There are not options for this taxonomy yet
42 |
43 | <%= content_tag :span, 'Create the first one', class: 'btn btn-primary js-toggle-elements',
44 | data: { show: 'taxonomy-option-create-form', hide: 'taxonomy-options-admin-add' } %>
45 | <% end %>
46 | <%= link_to 'Back to taxonomies list', taxonomies_path, class: 'btn' %>
47 |
--------------------------------------------------------------------------------
/app/views/threads/_topic_form.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%
3 | =begin
4 | Locals:
5 | index - integer index of the topic
6 | id - database id of the code
7 | name - name of the topic
8 | color - hex color for the topic
9 | description - text describing the topic
10 | =end
11 | human_topic_number = (Integer(index) + 1).to_s
12 | %>
13 |
14 | class="thumbnail">
15 |
16 | <%= hidden_field_tag "code_id[]", id %>
17 |
18 |
19 | <%= label_tag "topic_name_#{index}", "Topic #{human_topic_number}", :id => "topic_name_label_#{index}", :class => "control-label" %>
20 |
21 | <%= text_field_tag "topic_name_#{index}",name,placeholder: "Code/Topic name",:class=>"topic_name js_validate" %>
22 |
23 |
24 |
25 |
26 | <%= label_tag "topic_color_#{index}", "Topic #{human_topic_number} Color", :id => "topic_color_label_#{index}", :class => "control-label" %>
27 |
28 | <%= text_field_tag "topic_color_#{index}",color,placeholder: "#FF0000",:class=>"topic_color js_validate" %>
29 |
30 |
31 |
32 |
33 | <%= label_tag "topic_description_#{index}", "Topic #{human_topic_number} Description", :id => "topic_description_label_#{index}", :class => "control-label" %>
34 |
35 | <%= text_area_tag "topic_description_#{index}",description,:rows => "5",placeholder: "Some Info about that topic" %>
36 |
37 |
38 |
39 |
45 |
46 |
47 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/views/images/show.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Show image - PageOneX" %>
2 | <%- model_class = Image -%>
3 |
6 |
7 |
8 | <%= model_class.human_attribute_name(:publication_date) %>:
9 | <%= @image.publication_date %>
10 | <%= model_class.human_attribute_name(:size) %>:
11 | <%= @image.size %>
12 | <%= model_class.human_attribute_name(:media_id) %>:
13 | <%= @image.media_id %>
14 | <%= model_class.human_attribute_name(:image_name) %>:
15 | <%= @image.image_name %>
16 | <%= model_class.human_attribute_name(:source_url) %>:
17 | <%= link_to @image.source_url, @image.source_url %>
18 | <%= model_class.human_attribute_name(:missing) %>:
19 | <%= @image.missing %>
20 |
21 |
22 |
34 |
35 | <% if @image.missing %>
36 | Image is missing :-(
37 | <% else %>
38 |
39 | Thumbnail
40 | <%= image_tag @image.thumbnail_local_path(80,true), :alt => @image.image_name %>
41 |
42 |
43 | Full Size
44 | <%= image_tag @image.local_path, :alt => @image.image_name %>
45 |
46 | <% end %>
47 |
--------------------------------------------------------------------------------
/doc/local-install.md:
--------------------------------------------------------------------------------
1 | Install PageOneX locally
2 | ==========================
3 | Download the files from https://github.com/numeroteca/pageonex
4 |
5 | ### Needs
6 | PageOnex runs in Ruby on Rails, so you'll ned to install:
7 | + [Ruby v1.9.3](http://www.ruby-lang.org/en/downloads/) - We highly recommend using [RVM](http://rvm.io/) and gemsets to manage ruby (ie. `rvm use 1.9.3@pageonex`)
8 | + [RubyGems](https://rubygems.org/)
9 | + [Rails](https://rubyonrails.org/) (you might also want to install [RVM (Ruby Version Manager)](https://rvm.io/)
10 |
11 | Process
12 | -------
13 | You might want to clone the repository with git:
14 | ```
15 | git clone git@github.com:numeroteca/pageonex.git
16 | ```
17 |
18 | Or download the .zip file from https://github.com/numeroteca/pageonex/archive/master.zip
19 |
20 | Go to the directory
21 | ```
22 | cd pageonex
23 | ```
24 |
25 | Setup a database and then edit the `config/database.yml` file to give the app access to that database (we use MySQL).
26 |
27 | Install the gems
28 | ```
29 | bundle install
30 | ```
31 |
32 | Run the migration (this will create the database with its tables):
33 | ```
34 | rake db:migrate
35 | ```
36 |
37 | Create a PageOneX admin user like this:
38 | ```
39 | rails console
40 | User.create(:username=>'admin-user',:email=>'admin-user@admin.admin',:password=>'hola1234',:password_confirmation=>'hola1234')
41 | me = User.first
42 | me.admin = true
43 | me.save
44 | ```
45 |
46 | Load the list of newspapers into the data base:
47 | ```
48 | rake scraping:update_media
49 | ```
50 |
51 | Run the server:
52 | ```
53 | rails server
54 | ```
55 |
56 | You can now navigate the app at `http://localhost:3000/` or `http://0.0.0.0:3000/`
57 |
58 | ### Options
59 | If you have problems with the dependencies of the gems check this tricks.
60 |
61 | **Problems with dependencies**
62 |
63 | Run the same commands with 'bundle exec' like
64 | ```
65 | bundle exec rake db:migrate
66 | ```
67 |
68 | If you have problems with the pg gem, needed for the "heroku" version, you can run:
69 | ```
70 | bundle install --without heroku
71 | ```
72 |
73 |
74 |
--------------------------------------------------------------------------------
/app/views/images/index.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Image Index - PageOneX" %>
2 | <%- model_class = Image -%>
3 |
6 |
7 |
8 |
9 | <%= model_class.human_attribute_name(:id) %>
10 | <%= model_class.human_attribute_name(:publication_date) %>
11 | <%= model_class.human_attribute_name(:size) %>
12 | <%= model_class.human_attribute_name(:media_id) %>
13 | <%= model_class.human_attribute_name(:image_name) %>
14 | <%= model_class.human_attribute_name(:source_url) %>
15 | <%= model_class.human_attribute_name(:missing) %>
16 | <%= model_class.human_attribute_name(:created_at) %>
17 | <%=t '.actions', :default => t("helpers.actions") %>
18 |
19 |
20 |
21 | <% @images.each do |image| %>
22 |
23 | <%= link_to image.id, image_path(image) %>
24 | <%= image.publication_date %>
25 | <%= image.size %>
26 | <%= image.media_id %>
27 | <%= image.image_name %>
28 | <%= link_to image.source_url, image.source_url %>
29 | <%= image.missing %>
30 | <%=l image.created_at %>
31 |
32 | <%= link_to t('.edit', :default => t("helpers.links.edit")),
33 | edit_image_path(image), :class => 'btn btn-mini' %>
34 | <%= link_to t('.destroy', :default => t("helpers.links.destroy")),
35 | image_path(image),
36 | :method => :delete,
37 | :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
38 | :class => 'btn btn-mini btn-danger' %>
39 |
40 |
41 | <% end %>
42 |
43 |
44 |
45 | <%= link_to t('.new', :default => t("helpers.links.new")),
46 | new_image_path,
47 | :class => 'btn btn-primary' %>
48 |
--------------------------------------------------------------------------------
/app/views/layouts/embed.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | <%= @title %>
7 | <% @title = "PageOneX" %>
8 | <%= csrf_meta_tags %>
9 | <%= javascript_include_tag "application" %>
10 |
11 |
12 |
15 |
16 |
17 | <%= stylesheet_link_tag "application", :media => "all" %>
18 |
23 |
24 |
30 |
31 | <%= favicon_link_tag %>
32 |
33 |
36 |
37 |
38 | <%= yield %>
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
59 |
60 | <%= piwik_tracking_tag %>
61 |
62 |
63 |
--------------------------------------------------------------------------------
/app/controllers/users_controller.rb:
--------------------------------------------------------------------------------
1 | class UsersController < ApplicationController
2 |
3 | before_filter :authenticate_admin!
4 |
5 | # GET /users
6 | # GET /users.json
7 | def index
8 | @users = User.all
9 |
10 | respond_to do |format|
11 | format.html # index.html.erb
12 | format.json { render json: @users }
13 | end
14 | end
15 |
16 | # GET /users/1
17 | # GET /users/1.json
18 | def show
19 | @user = User.find(params[:id])
20 |
21 | respond_to do |format|
22 | format.html # show.html.erb
23 | format.json { render json: @user }
24 | end
25 | end
26 |
27 | # GET /users/new
28 | # GET /users/new.json
29 | def new
30 | @user = User.new
31 |
32 | respond_to do |format|
33 | format.html # new.html.erb
34 | format.json { render json: @user }
35 | end
36 | end
37 |
38 | # GET /users/1/edit
39 | def edit
40 | @user = User.find(params[:id])
41 | end
42 |
43 | # POST /users
44 | # POST /users.json
45 | def create
46 | @user = User.new(params[:user])
47 |
48 | respond_to do |format|
49 | if @user.save
50 | format.html { redirect_to @user, notice: 'User was successfully created.' }
51 | format.json { render json: @user, status: :created, location: @user }
52 | else
53 | format.html { render action: "new" }
54 | format.json { render json: @user.errors, status: :unprocessable_entity }
55 | end
56 | end
57 | end
58 |
59 | # PUT /users/1
60 | # PUT /users/1.json
61 | def update
62 | @user = User.find(params[:id])
63 |
64 | respond_to do |format|
65 | if @user.update_attributes(params[:user])
66 | format.html { redirect_to @user, notice: 'User was successfully updated.' }
67 | format.json { head :no_content }
68 | else
69 | format.html { render action: "edit" }
70 | format.json { render json: @user.errors, status: :unprocessable_entity }
71 | end
72 | end
73 | end
74 |
75 | # DELETE /users/1
76 | # DELETE /users/1.json
77 | def destroy
78 | @user = User.find(params[:id])
79 | @user.destroy
80 |
81 | respond_to do |format|
82 | format.html { redirect_to users_url }
83 | format.json { head :no_content }
84 | end
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/app/controllers/media_controller.rb:
--------------------------------------------------------------------------------
1 | class MediaController < ApplicationController
2 |
3 | before_filter :authenticate_admin!
4 |
5 | # GET /media
6 | # GET /media.json
7 | def index
8 | @media_list = Media.all
9 |
10 | respond_to do |format|
11 | format.html # index.html.erb
12 | format.json { render json: @media_list }
13 | end
14 | end
15 |
16 | # GET /media/1
17 | # GET /media/1.json
18 | def show
19 | @media = Media.find(params[:id])
20 |
21 | respond_to do |format|
22 | format.html # show.html.erb
23 | format.json { render json: @media }
24 | end
25 | end
26 |
27 | # GET /media/new
28 | # GET /media/new.json
29 | def new
30 | @media = Media.new
31 |
32 | respond_to do |format|
33 | format.html # new.html.erb
34 | format.json { render json: @media }
35 | end
36 | end
37 |
38 | # GET /media/1/edit
39 | def edit
40 | @media = Media.find(params[:id])
41 | end
42 |
43 | # POST /media
44 | # POST /media.json
45 | def create
46 | @media = Media.new(params[:media])
47 |
48 | respond_to do |format|
49 | if @media.save
50 | format.html { redirect_to @media, notice: 'Media was successfully created.' }
51 | format.json { render json: @media, status: :created, location: @media }
52 | else
53 | format.html { render action: "new" }
54 | format.json { render json: @media.errors, status: :unprocessable_entity }
55 | end
56 | end
57 | end
58 |
59 | # PUT /media/1
60 | # PUT /media/1.json
61 | def update
62 | @media = Media.find(params[:id])
63 |
64 | respond_to do |format|
65 | if @media.update_attributes(params[:media])
66 | format.html { redirect_to @media, notice: 'Media was successfully updated.' }
67 | format.json { head :no_content }
68 | else
69 | format.html { render action: "edit" }
70 | format.json { render json: @media.errors, status: :unprocessable_entity }
71 | end
72 | end
73 | end
74 |
75 | # DELETE /media/1
76 | # DELETE /media/1.json
77 | def destroy
78 | @media = Media.find(params[:id])
79 | @media.destroy
80 |
81 | respond_to do |format|
82 | format.html { redirect_to media_url }
83 | format.json { head :no_content }
84 | end
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/app/views/users/show.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "Users list - PageOneX" %>
2 | <%- model_class = User -%>
3 |
6 |
7 |
8 | <%= model_class.human_attribute_name(:username) %>:
9 | <%= @user.username %>
10 | <%= model_class.human_attribute_name(:email) %>:
11 | <%= @user.email %>
12 | <%= model_class.human_attribute_name(:encrypted_password) %>:
13 | <%= @user.encrypted_password %>
14 | <%= model_class.human_attribute_name(:reset_password_token) %>:
15 | <%= @user.reset_password_token %>
16 | <%= model_class.human_attribute_name(:reset_password_sent_at) %>:
17 | <%= @user.reset_password_sent_at %>
18 | <%= model_class.human_attribute_name(:remember_created_at) %>:
19 | <%= @user.remember_created_at %>
20 | <%= model_class.human_attribute_name(:current_sign_in_at) %>:
21 | <%= @user.current_sign_in_at %>
22 | <%= model_class.human_attribute_name(:last_sign_in_at) %>:
23 | <%= @user.last_sign_in_at %>
24 | <%= model_class.human_attribute_name(:current_sign_in_ip) %>:
25 | <%= @user.current_sign_in_ip %>
26 | <%= model_class.human_attribute_name(:last_sign_in_ip) %>:
27 | <%= @user.last_sign_in_ip %>
28 | <%= model_class.human_attribute_name(:admin) %>:
29 | <%= @user.admin %>
30 |
31 |
32 |
33 | <%= link_to t('.back', :default => t("helpers.links.back")),
34 | users_path, :class => 'btn' %>
35 | <%= link_to t('.edit', :default => t("helpers.links.edit")),
36 | edit_user_path(@user), :class => 'btn' %>
37 | <%= link_to t('.destroy', :default => t("helpers.links.destroy")),
38 | user_path(@user),
39 | :method => 'delete',
40 | :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
41 | :class => 'btn btn-danger' %>
42 |
43 |
--------------------------------------------------------------------------------
/doc/docker/running-pageonex-locally-with-docker-compose.md:
--------------------------------------------------------------------------------
1 | # Running pageonex locally with docker compose
2 |
3 | You can test locally pageonex using [docker compose](https://docs.docker.com/compose/).
4 |
5 | From the command line go to the direcrtory where you have cloned (or downloaded) the Pageonex repository and type:
6 |
7 | ```
8 | docker-compose up
9 | ```
10 |
11 | It will take a few minutes to complet the install.
12 | You need Internet access because it needs to download the PageOneX docker image.
13 |
14 | Once it works you will get:
15 |
16 | * A mysql database running [the official mysql image](https://hub.docker.com/_/mysql/).
17 | * All the migration and admin tasks run.
18 | * A pageonex server running [the lastest pageonex image](https://hub.docker.com/r/pageonex/pageonex).
19 | * All data stored in separate volumes that will remain even if you delete your application's containers.
20 |
21 | Once everything is running correctly, you can access the application from your browser at http://localhost:3000 or http://0.0.0.0:3000
22 |
23 | **For Windows users**
24 |
25 | You need to enable virtualization to allow docker work. See the example for Windows 11: https://support.microsoft.com/en-us/windows/enable-virtualization-on-windows-11-pcs-c5578302-6e43-4b4b-a449-8ced115f58e1
26 |
27 | ## Tasks
28 |
29 | ### How to run in detached mode
30 |
31 | In order to run docker-compose in background and have the shell available, please use detached mode
32 | ```
33 | docker-compose up -d
34 | ```
35 |
36 | ### How to see logs
37 |
38 | Logs are not shown in the screen in detached mode, you can inspect them using
39 | ```
40 | docker-compose logs
41 | ```
42 |
43 | ### How to access the rails console
44 |
45 | To get a the rails console (See [doc/local-install.md](/doc/local-install.md#process) for instructions on creating an admin user) run
46 | ```
47 | docker-compose exec app rails console
48 | ```
49 |
50 | ### How to access the database
51 |
52 | In case you want to further inspect the database, you can run
53 | ```
54 | docker-compose exec mysql mysql -u root -h localhost --password=root dc-prod
55 | ```
56 |
57 | ### How to shut it down
58 |
59 | If you want to shut down everything, keeping volumes and images for a quick start
60 | ```
61 | docker-compose stop
62 | ```
63 |
64 | ### How to delete everything and start from scratch
65 |
66 | You may want to start fresh. You have to make sure that all related images, containers are both stopped and deleted and volumes are deleted
67 | ```
68 | docker-compose stop
69 | docker-compose rm
70 | docker volume rm pageonex_app_kiosko_images pageonex_app_threads_images pageonex_db_data pageonex_app_tmp_dir
71 | ```
72 |
--------------------------------------------------------------------------------
/app/views/users/index.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "User list - PageOneX" %>
2 | <%- model_class = User -%>
3 |
6 |
7 |
8 |
9 | <%= model_class.human_attribute_name(:id) %>
10 | <%= model_class.human_attribute_name(:username) %>
11 | <%= model_class.human_attribute_name(:email) %>
12 | <%= model_class.human_attribute_name(:reset_password_token) %>
13 | <%= model_class.human_attribute_name(:reset_password_sent_at) %>
14 | <%= model_class.human_attribute_name(:remember_created_at) %>
15 | <%= model_class.human_attribute_name(:current_sign_in_at) %>
16 | <%= model_class.human_attribute_name(:last_sign_in_at) %>
17 | <%= model_class.human_attribute_name(:current_sign_in_ip) %>
18 | <%= model_class.human_attribute_name(:last_sign_in_ip) %>
19 | <%= model_class.human_attribute_name(:admin) %>
20 | <%= model_class.human_attribute_name(:created_at) %>
21 | <%=t '.actions', :default => t("helpers.actions") %>
22 |
23 |
24 |
25 | <% @users.each do |user| %>
26 |
27 | <%= link_to user.id, user_path(user) %>
28 | <%= user.username %>
29 | <%= user.email %>
30 | <%= user.reset_password_token %>
31 | <%= user.reset_password_sent_at %>
32 | <%= user.remember_created_at %>
33 | <%= user.current_sign_in_at %>
34 | <%= user.last_sign_in_at %>
35 | <%= user.current_sign_in_ip %>
36 | <%= user.last_sign_in_ip %>
37 | <%= user.admin %>
38 | <%=l user.created_at %>
39 |
40 | <%= link_to t('.edit', :default => t("helpers.links.edit")),
41 | edit_user_path(user), :class => 'btn btn-mini' %>
42 | <%= link_to t('.destroy', :default => t("helpers.links.destroy")),
43 | user_path(user),
44 | :method => :delete,
45 | :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
46 | :class => 'btn btn-mini btn-danger' %>
47 |
48 |
49 | <% end %>
50 |
51 |
52 |
53 | <%= link_to t('.new', :default => t("helpers.links.new")),
54 | new_user_path,
55 | :class => 'btn btn-primary' %>
56 |
--------------------------------------------------------------------------------
/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 vendor/assets/javascripts of plugins, if any, 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 | // the compiled file.
9 | //
10 | // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11 | // GO AFTER THE REQUIRES BELOW.
12 | //
13 | //= require jquery
14 | //= require jquery_ujs
15 |
16 | // require jquery.ui.all
17 |
18 | //= require jquery.ui.core
19 | //= require jquery.ui.widget
20 | //= require jquery.ui.mouse
21 | //= require jquery.ui.position
22 |
23 | //= require jquery.ui.draggable
24 | // require jquery.ui.droppable
25 | //= require jquery.ui.resizable
26 | // require jquery.ui.selectable
27 | // require jquery.ui.sortable
28 |
29 | //= require jquery.ui.accordion
30 | // require jquery.ui.autocomplete
31 | // require jquery.ui.button
32 | // require jquery.ui.dialog
33 | // require jquery.ui.slider
34 | // require jquery.ui.tabs
35 | //= require jquery.ui.datepicker
36 | //= require jquery.ui.datepicker-en-AU
37 | // require jquery.ui.progressbar
38 |
39 | // require jquery.ui.effect.all
40 | //= require jquery.ui.effect
41 | // require jquery.ui.effect-blind
42 | // require jquery.ui.effect-bounce
43 | // require jquery.ui.effect-clip
44 | // require jquery.ui.effect-drop
45 | // require jquery.ui.effect-explode
46 | // require jquery.ui.effect-fade
47 | // require jquery.ui.effect-fold
48 | // require jquery.ui.effect-highlight
49 | // require jquery.ui.effect-pulsate
50 | // require jquery.ui.effect-scale
51 | // require jquery.ui.effect-shake
52 | // require jquery.ui.effect-slide
53 | // require jquery.ui.effect-transfer
54 |
55 | //= require twitter/bootstrap/bootstrap-transition
56 | //= require twitter/bootstrap/bootstrap-alert
57 | //= require twitter/bootstrap/bootstrap-modal
58 | //= require twitter/bootstrap/bootstrap-dropdown
59 | //= require twitter/bootstrap/bootstrap-scrollspy
60 | // require twitter/bootstrap/bootstrap-tab
61 | //= require twitter/bootstrap/bootstrap-tooltip
62 | //= require twitter/bootstrap/bootstrap-popover
63 | //= require twitter/bootstrap/bootstrap-button
64 | //= require twitter/bootstrap/bootstrap-collapse
65 | // require twitter/bootstrap/bootstrap-typeahead
66 | //= require bootstrap-carousel
67 | // require twitter/bootstrap
68 |
69 | //= require spin.min
70 |
71 | //= require utils
72 | // require_tree .
73 |
74 | $(function() {
75 | // initialize any and all popovers on the page
76 | $('[rel="popover"]').popover({trigger:'hover'});
77 | })
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Pageonex::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 |
11 | # Disable Rails's static asset server (Apache or nginx will already do this)
12 | config.serve_static_assets = false
13 |
14 | # Compress JavaScripts and CSS
15 | config.assets.compress = true
16 |
17 | # Don't fallback to assets pipeline if a precompiled asset is missed
18 | config.assets.compile = true
19 |
20 | # Generate digests for assets URLs
21 | config.assets.digest = false
22 |
23 | # config.assets.initialize_on_precompile = false
24 |
25 | # Defaults to Rails.root.join("public/assets")
26 | # config.assets.manifest = YOUR_PATH
27 |
28 | # Specifies the header that your server uses for sending files
29 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
30 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
31 |
32 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
33 | # config.force_ssl = true
34 |
35 | # See everything in the log (default is :info)
36 | # config.log_level = :debug
37 |
38 | # Prepend all log lines with the following tags
39 | # config.log_tags = [ :subdomain, :uuid ]
40 |
41 | # Use a different logger for distributed setups
42 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
43 |
44 | # Use a different cache store in production
45 | # config.cache_store = :mem_cache_store
46 |
47 | # Enable serving of images, stylesheets, and JavaScripts from an asset server
48 | # config.action_controller.asset_host = "http://assets.example.com"
49 |
50 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
51 | # config.assets.precompile += %w( search.js )
52 |
53 | # Disable delivery errors, bad email addresses will be ignored
54 | config.action_mailer.delivery_method = :sendmail
55 | config.action_mailer.perform_deliveries = true
56 | config.action_mailer.raise_delivery_errors = false
57 | config.action_mailer.default_url_options = { :host => 'pageonex.com' }
58 |
59 | # Enable threaded mode
60 | # config.threadsafe!
61 |
62 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
63 | # the I18n.default_locale when a translation can not be found)
64 | config.i18n.fallbacks = true
65 |
66 | # Send deprecation notices to registered listeners
67 | config.active_support.deprecation = :notify
68 |
69 | # Log the query plan for queries taking more than this (works
70 | # with SQLite, MySQL, and PostgreSQL)
71 | # config.active_record.auto_explain_threshold_in_seconds = 0.5
72 | end
73 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | rackup DefaultRackup
2 |
3 | # Puma can serve each request in a thread from an internal thread pool.
4 | # The `threads` method setting takes two numbers: a minimum and maximum.
5 | # Any libraries that use thread pools should be configured to match
6 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
7 | # and maximum; this matches the default thread size of Active Record.
8 | #
9 | threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
10 | threads threads_count, threads_count
11 |
12 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
13 | #
14 | port ENV.fetch("PORT") { 3000 }
15 |
16 | # Specifies the `environment` that Puma will run in.
17 | #
18 | environment ENV.fetch("RAILS_ENV") { "development" }
19 |
20 | # Specifies the number of `workers` to boot in clustered mode.
21 | # Workers are forked webserver processes. If using threads and workers together
22 | # the concurrency of the application would be max `threads` * `workers`.
23 | # Workers do not work on JRuby or Windows (both of which do not support
24 | # processes).
25 | #
26 | workers ENV.fetch("WEB_CONCURRENCY") { 2 }
27 |
28 | # Use the `preload_app!` method when specifying a `workers` number.
29 | # This directive tells Puma to first boot the application and load code
30 | # before forking the application. This takes advantage of Copy On Write
31 | # process behavior so workers use less memory. If you use this option
32 | # you need to make sure to reconnect any threads in the `on_worker_boot`
33 | # block.
34 | #
35 | preload_app!
36 |
37 | # If you are preloading your application and using Active Record, it's
38 | # recommended that you close any connections to the database before workers
39 | # are forked to prevent connection leakage.
40 | #
41 | # before_fork do
42 | # ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
43 | # end
44 |
45 | before_fork do
46 | require 'puma_worker_killer'
47 |
48 | PumaWorkerKiller.enable_rolling_restart # Default is every 6 hours
49 | end
50 |
51 | # The code in the `on_worker_boot` will be called if you are using
52 | # clustered mode by specifying a number of `workers`. After each worker
53 | # process is booted, this block will be run. If you are using the `preload_app!`
54 | # option, you will want to use this block to reconnect to any threads
55 | # or connections that may have been created at application boot, as Ruby
56 | # cannot share connections between processes.
57 |
58 | on_worker_boot do
59 | # Valid on Rails up to 4.1 the initializer method of setting `pool` size
60 | ActiveSupport.on_load(:active_record) do
61 | config = ActiveRecord::Base.configurations[Rails.env] ||
62 | Rails.application.config.database_configuration[Rails.env]
63 | config['pool'] = ENV['RAILS_MAX_THREADS'] || 5
64 | ActiveRecord::Base.establish_connection(config)
65 | end
66 | end
67 |
68 | # Allow puma to be restarted by `rails restart` command.
69 | plugin :tmp_restart
70 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/coding.css.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the coding controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 | h1 {
5 | font-size: 30px;
6 | margin-top: 0;
7 | margin-bottom: 5px;
8 | }
9 | .legend_text {
10 | line-height: 1em;
11 | }
12 | .box_legend {
13 | width: 26px;
14 | height: 26px;
15 | display: block;
16 | margin: 0 4px 4px 0;
17 | float:left;
18 | cursor:pointer;
19 | }
20 | .inactive .box_legend {
21 | opacity:.4;
22 | }
23 | .legend_text:hover{
24 | font-weight:bold;
25 | cursor:pointer;
26 | }
27 | #color-legend li{
28 | vertical-align: top;
29 | }
30 | .codes_boxes{
31 | margin-left: 30px;
32 | font-size: 15px;
33 | }
34 |
35 | #aboveImageToolbar {
36 | margin-bottom: 10px;
37 | }
38 |
39 | .above-image-alert {
40 | margin-bottom: 0px;
41 | padding-top: 4px;
42 | padding-bottom: 4px;
43 | }
44 |
45 | .above-image-alert form {
46 | margin-bottom: 0px;
47 | }
48 |
49 | #chart-export-img {
50 | box-shadow: 2px 2px 5px #888888;
51 | }
52 |
53 | .high_area {
54 | border: 1px solid #333333;
55 | }
56 |
57 | #topics {
58 | padding-left:0px;
59 | }
60 | //Carrousel pointer
61 | #myCarousel{
62 | cursor:crosshair;
63 | }
64 | .ui-draggable{
65 | cursor:move;
66 | }
67 |
68 | /* dataviz */
69 | .gridline {
70 | stroke: #ddd;
71 | shape-rendering: crispEdges;
72 | stroke-width:1;
73 | }
74 |
75 | .yaxis line, .xaxis path{
76 | shape-rendering: crispEdges;
77 | stroke-width:1;
78 | }
79 |
80 | /* composite image stuff */
81 | ul.thread-composite-images {
82 | list-style-type: none;
83 | margin: 0px;
84 | padding: 0px;
85 | position: relative;
86 | display: block;
87 | }
88 | ul.thread-composite-images li {
89 | display: float;
90 | float: left;
91 | position: absolute;
92 | top: 0px;
93 | left: 0px;
94 | }
95 | ul.thread-coposite-labels {
96 | list-style-type: none;
97 | margin: 0px;
98 | padding: 0px;
99 | display: block;
100 | }
101 | ul.thread-coposite-labels li {
102 | display: block;
103 | vertical-align: top;
104 | text-align: right;
105 | cursor:pointer;
106 | }
107 | ul.thread-coposite-labels li.active {
108 | font-weight:bold;
109 | }
110 | ul.thread-coposite-labels li.inactive {
111 | font-weight:normal;
112 | }
113 | .avatar-icon {
114 | float:left;
115 | cursor:pointer;
116 | }
117 | .ha-user-name {
118 | margin-left: 25px;
119 | display: none;
120 | color: white;
121 | background-color: black;
122 | width: 150px;
123 | padding-left: 5px;
124 | }
125 | .user-id img:hover + span {
126 | display: block !important;
127 | }
128 | .ha-close-icon {
129 | cursor:pointer;
130 | width: 20px;
131 | position: absolute;
132 | right: 0px;
133 | top: 0px;
134 | }
135 | .ha-edit-icon {
136 | cursor:pointer;
137 | width: 20px;
138 | position: absolute;
139 | right: 23px;
140 | top: 0px;
141 | }
142 | #embedded_footer{
143 | position: absolute;
144 | right: 0px;
145 | bottom: 0px;
146 | /*background-image: url("/images/header-proyecto.gif");*/
147 | background-color:#ddd;
148 | padding:3px;
149 | }
150 | #color-legend li{
151 | width:150px;
152 | padding:0;
153 | }
154 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Pageonex::Application.routes.draw do
2 | devise_for :users
3 | resources :users
4 |
5 | match 'threads/mine' => 'threads#mine'
6 | match 'threads/by/:username' => 'threads#by_username'
7 | match 'threads/search' => 'threads#search'
8 | match 'threads/search_by_category' => 'threads#search_by_category'
9 | match 'threads/new_topic/:index' => 'threads#new_topic'
10 | resources :threads do
11 | member do
12 | post :fork
13 | end
14 | end
15 |
16 | match 'images/download' => 'images#download'
17 | match 'images/for_media/:media_id' => 'images#for_media'
18 | resources :images
19 |
20 | resources :media
21 |
22 | resources :taxonomies, except: [:show] do
23 | resources :taxonomy_options, except: [:show, :new]
24 | end
25 |
26 | match ':username/:thread_name/export' => 'threads#export'
27 | match ':username/:thread_name/raw' => 'threads#raw'
28 | match ':username/:thread_name/coding' => 'coding#process_images'
29 | match ':username/:thread_name/process_highlighted_areas' => 'coding#process_highlighted_areas'
30 | match ':username/:thread_name' => 'coding#display'
31 | match ':username/:thread_name/embed' => 'coding#embed'
32 |
33 | match '/about' => 'home#about'
34 | match '/help' => 'home#help'
35 | match '/terms-of-service' => 'home#terms-of-service'
36 | match '/privacy-policy' => 'home#privacy-policy'
37 | match '/export_chart' => 'home#export_chart'
38 |
39 | root :to => "home#index"
40 |
41 |
42 |
43 | # The priority is based upon order of creation:
44 | # first created -> highest priority.
45 |
46 | # Sample of regular route:
47 | # match 'products/:id' => 'catalog#view'
48 | # Keep in mind you can assign values other than :controller and :action
49 |
50 | # Sample of named route:
51 | # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
52 | # This route can be invoked with purchase_url(:id => product.id)
53 |
54 | # Sample resource route (maps HTTP verbs to controller actions automatically):
55 | # resources :products
56 |
57 | # Sample resource route with options:
58 | # resources :products do
59 | # member do
60 | # get 'short'
61 | # post 'toggle'
62 | # end
63 | #
64 | # collection do
65 | # get 'sold'
66 | # end
67 | # end
68 |
69 | # Sample resource route with sub-resources:
70 | # resources :products do
71 | # resources :comments, :sales
72 | # resource :seller
73 | # end
74 |
75 | # Sample resource route with more complex sub-resources
76 | # resources :products do
77 | # resources :comments
78 | # resources :sales do
79 | # get 'recent', :on => :collection
80 | # end
81 | # end
82 |
83 | # Sample resource route within a namespace:
84 | # namespace :admin do
85 | # # Directs /admin/products/* to Admin::ProductsController
86 | # # (app/controllers/admin/products_controller.rb)
87 | # resources :products
88 | # end
89 |
90 | # You can have the root of your site routed with "root"
91 | # just remember to delete public/index.html.
92 | # root :to => 'welcome#index'
93 |
94 | # See how all your routes lay out with "rake routes"
95 |
96 | # This is a legacy wild controller route that's not recommended for RESTful applications.
97 | # Note: This route will make all actions in every controller accessible via GET requests.
98 | # match ':controller(/:action(/:id))(.:format)'
99 | end
100 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | # Pick the frameworks you want:
4 | require "active_record/railtie"
5 | require "action_controller/railtie"
6 | require "action_mailer/railtie"
7 | require "active_resource/railtie"
8 | require "sprockets/railtie"
9 | # require "rails/test_unit/railtie"
10 | require "csv"
11 |
12 | if defined?(Bundler)
13 | # If you precompile assets before deploying to production, use this line
14 | Bundler.require(*Rails.groups(:assets => %w(development test)))
15 | # If you want your assets lazily compiled in production, use this line
16 | # Bundler.require(:default, :assets, Rails.env)
17 | end
18 |
19 | module Pageonex
20 | class Application < Rails::Application
21 | # Settings in config/environments/* take precedence over those specified here.
22 | # Application configuration should go into files in config/initializers
23 | # -- all .rb files in that directory are automatically loaded.
24 |
25 | # Custom directories with classes and modules you want to be autoloadable.
26 | # config.autoload_paths += %W(#{config.root}/extras)
27 | config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
28 |
29 |
30 | # Only load the plugins named here, in the order given (default is alphabetical).
31 | # :all can be used as a placeholder for all plugins not explicitly named.
32 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
33 |
34 | # Activate observers that should always be running.
35 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
36 |
37 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
38 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
39 | # config.time_zone = 'Central Time (US & Canada)'
40 |
41 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
42 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
43 | # config.i18n.default_locale = :de
44 |
45 | # Configure the default encoding used in templates for Ruby 1.9.
46 | config.encoding = "utf-8"
47 |
48 | # Configure sensitive parameters which will be filtered from the log file.
49 | config.filter_parameters += [:password]
50 |
51 | # Use SQL instead of Active Record's schema dumper when creating the database.
52 | # This is necessary if your schema can't be completely dumped by the schema dumper,
53 | # like if you have constraints or database-specific column types
54 | # config.active_record.schema_format = :sql
55 |
56 | # Enforce whitelist mode for mass assignment.
57 | # This will create an empty whitelist of attributes available for mass-assignment for all models
58 | # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
59 | # parameters by using an attr_accessible or attr_protected declaration.
60 | # config.active_record.whitelist_attributes = true
61 |
62 | # Enable the asset pipeline
63 | config.assets.enabled = true
64 |
65 | # Version of your assets, change this if you want to expire all your assets
66 | config.assets.version = '1.0'
67 |
68 | # Load custom environment variables
69 | config.before_configuration do
70 | env_file = File.join(Rails.root, 'config', 'local_env.yml')
71 | YAML.load(File.open(env_file)).each do |key, value|
72 | ENV[key.to_s] = value
73 | end if File.exists?(env_file)
74 | end
75 | end
76 | end
77 |
--------------------------------------------------------------------------------
/app/controllers/images_controller.rb:
--------------------------------------------------------------------------------
1 | class ImagesController < ApplicationController
2 |
3 | before_filter :authenticate_admin!, :except => [:download]
4 |
5 | def download
6 | image_id = params[:missing_image_id]
7 | thread_id = params[:thread_id]
8 | # try to download the image again
9 | image = Image.find(image_id)
10 | downloaded_something = image.download
11 | image.save
12 | # redirect back to the image in the thread
13 | if thread_id=='0'
14 | # TODO: this needs to flush the composite image cache on all the threads that use this
15 | if downloaded_something
16 | flash[:notice] = "Download the image"
17 | else
18 | flash[:error] = "Didn't download anything!"
19 | end
20 | redirect_to '/images/'+image_id
21 | else
22 | thread = Threadx.find(thread_id)
23 | # TODO: should this flush the composite images on ALL the threads that use this image?
24 | thread.remove_composite_images if downloaded_something # flush the generated composite images because there is a new highlighted area
25 | redirect_to thread.link_url+"coding?i="+image.id.to_s
26 | end
27 | end
28 |
29 | def for_media
30 | @images = Image.where(:media_id=>params[:media_id])
31 | render :index
32 | end
33 |
34 | # GET /images
35 | # GET /images.json
36 | def index
37 | @images = Image.all(:limit=>100)
38 |
39 | respond_to do |format|
40 | format.html # index.html.erb
41 | format.json { render json: @images }
42 | end
43 | end
44 |
45 | # GET /images/1
46 | # GET /images/1.json
47 | def show
48 | @image = Image.find(params[:id])
49 |
50 | respond_to do |format|
51 | format.html # show.html.erb
52 | format.json { render json: @image }
53 | end
54 | end
55 |
56 | # GET /images/new
57 | # GET /images/new.json
58 | def new
59 | @image = Image.new
60 |
61 | respond_to do |format|
62 | format.html # new.html.erb
63 | format.json { render json: @image }
64 | end
65 | end
66 |
67 | # GET /images/1/edit
68 | def edit
69 | @image = Image.find(params[:id])
70 | end
71 |
72 | # POST /images
73 | # POST /images.json
74 | def create
75 | @image = Image.new(params[:image])
76 |
77 | respond_to do |format|
78 | if @image.save
79 | format.html { redirect_to @image, notice: 'Image was successfully created.' }
80 | format.json { render json: @image, status: :created, location: @image }
81 | else
82 | format.html { render action: "new" }
83 | format.json { render json: @image.errors, status: :unprocessable_entity }
84 | end
85 | end
86 | end
87 |
88 | # PUT /images/1
89 | # PUT /images/1.json
90 | def update
91 | @image = Image.find(params[:id])
92 |
93 | respond_to do |format|
94 | if @image.update_attributes(params[:image])
95 | format.html { redirect_to @image, notice: 'Image was successfully updated.' }
96 | format.json { head :no_content }
97 | else
98 | format.html { render action: "edit" }
99 | format.json { render json: @image.errors, status: :unprocessable_entity }
100 | end
101 | end
102 | end
103 |
104 | # DELETE /images/1
105 | # DELETE /images/1.json
106 | def destroy
107 | @image = Image.find(params[:id])
108 | @image.destroy
109 |
110 | respond_to do |format|
111 | format.html { redirect_to images_url }
112 | format.json { head :no_content }
113 | end
114 | end
115 | end
116 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the top of the
9 | * compiled file, but it's generally better to create a new file per style scope.
10 | *
11 | *= require_self
12 | *= require_tree .
13 | */
14 |
15 | /*
16 | *= require jquery.ui.core
17 | *= require jquery.ui.theme
18 | */
19 |
20 | /*
21 | *= require jquery.ui.resizable
22 | *= require jquery.ui.selectable
23 | */
24 |
25 | /*
26 | *= require jquery.ui.accordion
27 | * require jquery.ui.autocomplete
28 | * require jquery.ui.button
29 | *= require jquery.ui.dialog
30 | * require jquery.ui.slider
31 | * require jquery.ui.tabs
32 | *= require jquery.ui.datepicker
33 | * require jquery.ui.progressbar
34 | */
35 |
36 | #login-info {
37 | margin-top: 3px;
38 | margin-left: 10px;
39 | }
40 | #login-info h5 {
41 | line-height: 16px;
42 | margin: 0px;
43 | }
44 | #datavis .images .span1{
45 | margin-left: 0;
46 | }
47 | .thumb-img-coded {
48 | opacity: 0.3;
49 | }
50 | .thumb-img-no-coded {
51 | opacity: 0.7;
52 | }
53 | .custom-link{
54 | color:#000;
55 | }
56 |
57 | #footer {
58 | margin-bottom: 40px;
59 | }
60 | .categories a {
61 | color:#fff !important;
62 | }
63 |
64 | .yaxis path {
65 | display:none;
66 | }
67 |
68 | /*----------------new menu----------*/
69 | .pageonex-brand {
70 | text-shadow: 0 0px 0 !important;
71 | padding: 5px 20px 10px;
72 | }
73 | #pre-menu{
74 | margin-top:6px;
75 | }
76 | #pre-menu li a {
77 | display: block!important;
78 | display: block;
79 | position: relative;
80 | text-decoration: none;
81 | z-index: 999;
82 | }
83 | #pre-menu li:hover,
84 | #pre-menu li a:hover,
85 | #pre-menu li:hover a {
86 | text-decoration: none;
87 | position: relative;
88 | z-index: 999;
89 | }
90 | #pre-menu li ul {
91 | display: none;
92 | position: absolute;
93 | z-index: 999;
94 | width: 150px;
95 | font-weight: bold;
96 | left: 0;
97 | padding: 2px 0 5px;
98 | margin: 0 !important;
99 | }
100 | #pre-menu li a:hover ul,
101 | #pre-menu li:hover ul {
102 | display: block !important;
103 | }
104 | #pre-menu li a:hover ul li,
105 | #pre-menu li:hover ul li {
106 | position: relative;
107 | display: block;
108 | margin: 0 !important;
109 | padding: 0 !important;
110 | z-index: 999;
111 | background-color: #fff;
112 | }
113 | #pre-menu li a:hover ul li a,
114 | #pre-menu li:hover ul li a {
115 | padding: 2px 0 8px 5 !important;
116 | }
117 | #pre-menu li ul li:hover{
118 | /*background-color: #bbb;*/
119 | }
120 | #pre-menu li ul li{
121 | border:0;
122 | }
123 | #pre-menu ul.dropdown-menu li a{
124 | color:gray;
125 | }
126 | #pre-menu ul.dropdown-menu li a:hover{
127 | color:white !important;
128 | }
129 | .navbar .navbar-inner{
130 | background-image:none;
131 | }
132 | #main-menu ul li {
133 | background-color:#a1a1a1;
134 | margin-right: 5px;
135 | }
136 | #main-menu li:hover {
137 | background-color:#ff9955;
138 | }
139 |
140 | #main-menu li a{
141 | color:white;
142 | text-shadow: 0 0px 0 white;
143 | padding: 5px;
144 | }
145 | #main-menu li.current-menu-item{
146 | background-color:white;
147 | }
148 | #main-menu li.current-menu-item a{
149 | color:#a1a1a1;
150 | }
151 |
--------------------------------------------------------------------------------
/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2 |
3 | en:
4 | errors:
5 | messages:
6 | expired: "has expired, please request a new one"
7 | not_found: "not found"
8 | already_confirmed: "was already confirmed, please try signing in"
9 | not_locked: "was not locked"
10 | not_saved:
11 | one: "1 error prohibited this %{resource} from being saved:"
12 | other: "%{count} errors prohibited this %{resource} from being saved:"
13 |
14 | devise:
15 | failure:
16 | already_authenticated: 'You are already signed in.'
17 | unauthenticated: 'You need to sign in or sign up before continuing.'
18 | unconfirmed: 'You have to confirm your account before continuing.'
19 | locked: 'Your account is locked.'
20 | invalid: 'Invalid email or password.'
21 | invalid_token: 'Invalid authentication token.'
22 | timeout: 'Your session expired, please sign in again to continue.'
23 | inactive: 'Your account was not activated yet.'
24 | sessions:
25 | signed_in: 'Signed in successfully.'
26 | signed_out: 'Signed out successfully.'
27 | passwords:
28 | send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
29 | updated: 'Your password was changed successfully. You are now signed in.'
30 | updated_not_active: 'Your password was changed successfully.'
31 | send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
32 | confirmations:
33 | send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
34 | send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
35 | confirmed: 'Your account was successfully confirmed. You are now signed in.'
36 | registrations:
37 | signed_up: 'Welcome! You have signed up successfully.'
38 | signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
39 | signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
40 | signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
41 | updated: 'You updated your account successfully.'
42 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
43 | destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
44 | unlocks:
45 | send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
46 | unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'
47 | send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
48 | omniauth_callbacks:
49 | success: 'Successfully authorized from %{kind} account.'
50 | failure: 'Could not authorize you from %{kind} because "%{reason}".'
51 | mailer:
52 | confirmation_instructions:
53 | subject: 'Confirmation instructions'
54 | reset_password_instructions:
55 | subject: 'Reset password instructions'
56 | unlock_instructions:
57 | subject: 'Unlock Instructions'
58 |
--------------------------------------------------------------------------------
/app/assets/javascripts/spin.min.js:
--------------------------------------------------------------------------------
1 | //fgnass.github.com/spin.js#v1.2.5
2 | (function(a,b,c){function g(a,c){var d=b.createElement(a||"div"),e;for(e in c)d[e]=c[e];return d}function h(a){for(var b=1,c=arguments.length;b>1):c.left+e)+"px",top:(c.top=="auto"?i.y-h.y+(a.offsetHeight>>1):c.top+e)+"px"})),d.setAttribute("aria-role","progressbar"),b.lines(d,b.opts);if(!f){var j=0,k=c.fps,m=k/c.speed,o=(1-c.opacity)/(m*c.trail/100),p=m/c.lines;!function q(){j++;for(var a=c.lines;a;a--){var e=Math.max(1-(j+a*p)%m*o,c.opacity);b.opacity(d,c.lines-a,e,c)}b.timeout=b.el&&setTimeout(q,~~(1e3/k))}()}return b},stop:function(){var a=this.el;return a&&(clearTimeout(this.timeout),a.parentNode&&a.parentNode.removeChild(a),this.el=c),this},lines:function(a,b){function e(a,d){return l(g(),{position:"absolute",width:b.length+b.width+"px",height:b.width+"px",background:a,boxShadow:d,transformOrigin:"left",transform:"rotate("+~~(360/b.lines*c+b.rotate)+"deg) translate("+b.radius+"px"+",0)",borderRadius:(b.width>>1)+"px"})}var c=0,d;for(;c',b)}var b=l(g("group"),{behavior:"url(#default#VML)"});!k(b,"transform")&&b.adj?(i.addRule(".spin-vml","behavior:url(#default#VML)"),p.prototype.lines=function(b,c){function f(){return l(a("group",{coordsize:e+" "+e,coordorigin:-d+" "+ -d}),{width:e,height:e})}function k(b,e,g){h(i,h(l(f(),{rotation:360/c.lines*b+"deg",left:~~e}),h(l(a("roundrect",{arcsize:1}),{width:d,height:c.width,left:c.radius,top:-c.width>>1,filter:g}),a("fill",{color:c.color,opacity:c.opacity}),a("stroke",{opacity:0}))))}var d=c.length+c.width,e=2*d,g=-(c.width+c.length)*2+"px",i=l(f(),{position:"absolute",top:g,left:g}),j;if(c.shadow)for(j=1;j<=c.lines;j++)k(j,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(j=1;j<=c.lines;j++)k(j);return h(b,i)},p.prototype.opacity=function(a,b,c,d){var e=a.firstChild;d=d.shadow&&d.lines||0,e&&b+d", "/": "?", "\\": "|"
32 | }
33 | };
34 |
35 | function keyHandler( handleObj ) {
36 | // Only care when a possible input has been specified
37 | if ( typeof handleObj.data !== "string" ) {
38 | return;
39 | }
40 |
41 | var origHandler = handleObj.handler,
42 | keys = handleObj.data.toLowerCase().split(" "),
43 | textAcceptingInputTypes = ["text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color"];
44 |
45 | handleObj.handler = function( event ) {
46 | // Don't fire in text-accepting inputs that we didn't directly bind to
47 | if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
48 | jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1 ) ) {
49 | return;
50 | }
51 |
52 | // Keypress represents characters, not special keys
53 | var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ],
54 | character = String.fromCharCode( event.which ).toLowerCase(),
55 | key, modif = "", possible = {};
56 |
57 | // check combinations (alt|ctrl|shift+anything)
58 | if ( event.altKey && special !== "alt" ) {
59 | modif += "alt+";
60 | }
61 |
62 | if ( event.ctrlKey && special !== "ctrl" ) {
63 | modif += "ctrl+";
64 | }
65 |
66 | // TODO: Need to make sure this works consistently across platforms
67 | if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
68 | modif += "meta+";
69 | }
70 |
71 | if ( event.shiftKey && special !== "shift" ) {
72 | modif += "shift+";
73 | }
74 |
75 | if ( special ) {
76 | possible[ modif + special ] = true;
77 |
78 | } else {
79 | possible[ modif + character ] = true;
80 | possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
81 |
82 | // "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
83 | if ( modif === "shift+" ) {
84 | possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
85 | }
86 | }
87 |
88 | for ( var i = 0, l = keys.length; i < l; i++ ) {
89 | if ( possible[ keys[i] ] ) {
90 | return origHandler.apply( this, arguments );
91 | }
92 | }
93 | };
94 | }
95 |
96 | jQuery.each([ "keydown", "keyup", "keypress" ], function() {
97 | jQuery.event.special[ this ] = { add: keyHandler };
98 | });
99 |
100 | })( jQuery );
--------------------------------------------------------------------------------
/doc/docker/development-with-docker-compose.md:
--------------------------------------------------------------------------------
1 | # Developing pageonex with docker-compose
2 |
3 | If you need to do development in pageonex without the hassle of installing all the dependencies you can use our [docker-compose-build file](/docker-compose-build.yml) which builds the application from scratch.
4 |
5 | 1. In order to start the pageonex and mysql containers, run from the root of this repository:
6 | ```
7 | docker-compose -f docker-compose-build.yml up -d --build
8 | ```
9 |
10 | You might get this error `Couldn’t connect to Docker daemon at http+docker://localhost – is it running?`, it is possible to fix [with this solution](https://techoverflow.net/2019/03/16/how-to-fix-error-couldnt-connect-to-docker-daemon-at-httpdocker-localhost-is-it-running/):
11 |
12 | > There are two possible reasons for this error message.
13 | > The common reason is that the user you are running the command as does not have the permissions to access docker.
14 | > You can fix this either by running the command as root using sudo (since root has the permission to access docker) or adding your user to the docker group: `sudo usermod -a -G docker $USER`
15 | > and then logging out and logging back in completely (or restarting the system/server).
16 | > The other reason is that you have not started docker. On Ubuntu, you can start it using `sudo systemctl enable docker` (Auto-start on boot) and `sudo systemctl start docker` (Start right now).
17 |
18 | > You can also get this message: `Creating pageonex_mysql_build_1 ... error ERROR: for pageonex_mysql_build_1 Cannot start service mysql_build: driver failed programming external connectivity on endpoint pageonex_mysql_build_1 (34af946d85db80f663a8d71e550bef50128a3fd4f41593bdc9ef722a7c2f5b54): Bind for 0.0.0.0:23306 failed: port is already allocated` this is because you have another docker container running using that port.
19 | > Use `docker ps` to see which other containers you have and stop them by using the `CONTAINER ID`. If container id is `03be2d8e8337` use `docker stop 03be2d8e8337`
20 |
21 |
22 | 2. To create the initial database:
23 | ```
24 | docker-compose -f docker-compose-build.yml exec app_build rake db:migrate --trace
25 | ```
26 |
27 | 3. To load the list of newspapers into the data base run:
28 | ```
29 | docker-compose -f docker-compose-build.yml exec app_build rake scraping:update_media --trace
30 | ```
31 |
32 | Once everything is running correctly, you can access the application from your browser at http://localhost:3000 or http://0.0.0.0:3000
33 |
34 | ## Tasks
35 |
36 | ### How to access the rails console
37 |
38 | To get a the rails console (See [doc/local-install.md](/doc/local-install.md#process) for instructions on creating an admin user)
39 | ```
40 | docker-compose -f docker-compose-build.yml exec app_build rails console
41 | ```
42 |
43 | Once you have entered the rails console you can make one user admin with this command:
44 |
45 | ```
46 | User.find_by_email('user@domain.com').update_attribute :admin, true
47 | ```
48 |
49 | Admin users are able to use the taxonomies feature.
50 |
51 | To quit the console type `quit`.
52 |
53 | ### How to access the database
54 |
55 | If you want to log in the mysql database
56 | ```
57 | docker-compose -f docker-compose-build.yml exec app_build mysql -u root --password=root dc-dev
58 | ```
59 |
60 | ### How to rebuild your container
61 |
62 | If you make changes in the app and you want to rebuild your container
63 | ```
64 | docker-compose -f docker-compose-build.yml up -d --build
65 | ```
66 |
67 | ### How to see rails logs
68 |
69 | If you want to inspect the logs
70 | ```
71 | docker-compose -f docker-compose-build.yml logs
72 | ```
73 |
74 | ### How to shut down the app
75 |
76 | If you want to shut down everything
77 | ```
78 | docker-compose -f docker-compose-build.yml stop
79 | ```
80 |
81 | ### How to remove everythung and start from scratch
82 |
83 | If you want to remove everything and have a new and clean environment
84 | ```
85 | docker-compose -f docker-compose-build.yml rm -s -v
86 | docker volume rm build_db_data build_app_data
87 | ```
88 |
--------------------------------------------------------------------------------
/app/models/image.rb:
--------------------------------------------------------------------------------
1 | require 'RMagick'
2 | require "open-uri"
3 |
4 | class Image < ActiveRecord::Base
5 | belongs_to :media
6 |
7 | has_many :highlighted_areas
8 |
9 | default_scope order("publication_date ASC, media_id ASC")
10 |
11 | before_save :check_if_missing
12 |
13 | def width
14 | return size[0..(size.index('x'))].to_i
15 | end
16 |
17 | def height
18 | length = size.length - size.index('x') - 1;
19 | return size[-1*length, length].to_i
20 | end
21 |
22 | def self.codeable
23 | where(:missing=>false)
24 | end
25 |
26 | def self.by_media(media_ids)
27 | where(:media_id => media_ids)
28 | end
29 |
30 | def self.by_date(dates)
31 | where(:publication_date => dates)
32 | end
33 |
34 | def self.publication_date
35 | select('publication_date').uniq.map { |elt| elt.publication_date }
36 | end
37 |
38 | def thumbnail_local_path width=80, generate=true
39 | path = self.local_path.chomp(File.extname(self.local_path))+'-thumb-'+width.to_s+'.jpg'
40 | self.thumbnail width if generate
41 | path
42 | end
43 |
44 | def image_height_at_width other_width
45 | (other_width.to_f / self.width) * self.height
46 | end
47 |
48 | # return a Magick img object that is a thumbnail (caches to disk) - nil if image missing or messed up
49 | def thumbnail width, path=nil
50 | return nil unless File.exists? self.full_local_path # bail if there is no image
51 | if path==nil
52 | thumb_file_path = File.join 'app','assets','images',self.thumbnail_local_path(width,false)
53 | else
54 | thumb_file_path = File.join 'app','assets','images', path
55 | end
56 | return Magick::Image.read(thumb_file_path).first if File.exists?(thumb_file_path) and File.size?(thumb_file_path)
57 | # if the thumb doesn't exist then generate it
58 | img_thumb = nil
59 | return img_thumb if not File.size? self.full_local_path
60 | begin
61 | img = Magick::Image.read(self.full_local_path).first
62 | scale = width.to_f / img.columns.to_f
63 | img_thumb = img.thumbnail(scale)
64 | img_thumb.write thumb_file_path
65 | rescue Magick::ImageMagickError=>e
66 | logger.error "Image Empty Error in image.thumbnail: #{e}"
67 | end
68 | return img_thumb
69 | end
70 |
71 | def local_path
72 | File.join('kiosko', self.media.image_directory_name, self.image_name + ".jpg")
73 | end
74 |
75 | def download
76 | if Pageonex::Application.config.use_local_images
77 | # make the media dir if you need to
78 | self.media.create_image_directory
79 | # try to fetch the image
80 | begin
81 | File.open(self.full_local_path, "wb") { |f| f.write(open(self.source_url).read) }
82 | if File.size? self.full_local_path
83 | # TODO we should check the file size here to see if it is zero (raise exception if it is)
84 | File.open(self.full_local_path,"rb") do |f|
85 | size_info = ImageSize.new(f.read).get_size
86 | self.size = "#{size_info[0]}x#{size_info[1]}"
87 | end
88 | self.missing = false
89 | else
90 | self.size = '750x951'
91 | logger.debug "Image Download Failed:#{id}: got a zero size image for #{source_url}"
92 | end
93 | rescue Exception => e
94 | # image doesn't exist on their server :-(
95 | logger.debug "Image Download Failed:#{id}: couldn't find image at #{source_url} (#{e.message})"
96 | self.size = '750x951'
97 | self.missing = true
98 | end
99 | else
100 | url = URI.parse(self.source_url)
101 | request = Net::HTTP.new(url.host, url.port)
102 | response = request.request_head(url.path)
103 | self.size = '750x951' #!!this value of pixels is 'hard coded' so it gives wrong values for long newspapers
104 | self.missing = (response.code != "200")
105 | end
106 | !missing
107 | end
108 |
109 | def full_local_path
110 | File.join('app','assets','images', self.local_path)
111 | end
112 |
113 | private
114 |
115 | # Backup strategy: default the "missing" column smartly if it isn't filled in
116 | # (even though the scraper should have filled it in)
117 | def check_if_missing
118 | if self.missing.nil?
119 | if Pageonex::Application.config.use_local_images
120 | self.missing = self.local_path.nil?
121 | else
122 | self.missing = self.source_url.nil?
123 | end
124 | end
125 | end
126 |
127 | end
128 |
--------------------------------------------------------------------------------
/app/views/coding/embed.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "#{@thread.thread_display_name} - Embedded- PageOneX" %>
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 | <% @img_map_info['row_info'].each do |media_id,info| %>
13 | <%=info['name']%>
14 | <% end %>
15 |
16 |
17 |
18 |
19 | <%= image_tag @thread.path_to_composite_cover_image %>
20 | <% @thread.codes.each do |code| %>
21 | <%= image_tag @thread.path_to_composite_highlighed_area_image code.id %>
22 | <% end %>
23 | <%=image_tag 'transparent.png', :style=>"width:#{@img_map_info['width']}px;height:#{@img_map_info['height']}px;", :name=>'front-page-images', :usemap=>'#front-page-images'%>
24 |
25 |
26 | <% @img_map_info['images'].each_pair do |image_id, image_info| %>
27 |
29 | <% end %>
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
<%= @thread.thread_display_name %>
38 |
<%= @thread.start_date.inspect %> - <%= @thread.end_date.inspect %>
39 |
40 | <% @thread.codes.each do |code| %>
41 |
42 |
43 | <%= code.code_text %>
44 |
45 | <% end %>
46 |
47 |
48 |
49 |
50 |
51 |
52 | <%= javascript_include_tag "d3.v3.min.js" %>
53 | <%= javascript_include_tag "dataviz.js" %>
54 |
55 |
78 |
79 |
90 |
91 | <%= javascript_tag do %> //activates and deactivates composite images clicking on legend
92 | <% @thread.codes.each do |code| %>
93 | d3.select('#code_<%= code.id %>').on('click',function() {
94 | if (d3.select(this).attr('class')==='active'){
95 | d3.select("#composite_image_code_<%= code.id %>").style("display", "none");
96 | d3.select(this).attr("class","inactive");
97 | } else {
98 | d3.select("#composite_image_code_<%= code.id %>").style("display", "block");
99 | d3.select(this).attr("class","active");
100 | }
101 | });
102 | <% end %>
103 | <% end %>
104 |
--------------------------------------------------------------------------------
/app/views/threads/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <% @title = @subtitle+" - PageOneX" %>
3 | <% if flash[:thread_name_error] %>
4 |
5 |
×
6 |
<%= flash[:thread_name_error] %>
7 |
8 | <% end %>
9 |
10 |
<%=@subtitle%>
11 |
12 |
13 |
<%= raw @bio %>
14 |
15 |
16 | <% if @threads.length > 0%>
17 |
18 | <% @threads.each_with_index do |thread, i| %>
19 |
20 |
21 |
43 |
44 |
<%= link_to thread.thread_display_name, thread_url(thread) %>
45 |
by <%=threads_by_user_link thread.owner %> | From <%= thread.start_date %> to <%= thread.end_date %>
46 |
<%= strip_tags(sanitize(thread.description.truncate(150))) %>
47 |
48 | <% if current_user.nil? %>
49 |
50 | <% elsif thread.owner == current_user or current_user.admin %>
51 |
52 | <%= link_to "View", thread_url(thread), :class => "btn btn-small" %>
53 | <%= link_to "Edit", "/threads/#{thread.thread_name}/edit/", :class => "btn btn-small" %>
54 | <%= link_to "Code", "/threads/#{thread.thread_name}/coding/", :class => "btn btn-small" %>
55 | <%= link_to "Delete", "/threads/#{thread.thread_name}" ,:method=>"delete" , :class => "btn btn-small btn-danger delete" %>
56 |
57 | <% end %>
58 |
59 |
60 | <% thread.category_list.each do |c| %>
61 | <%=link_to c,"/threads/search_by_category?q=#{c.strip}", :class => "label"%>
62 | <% end %>
63 |
64 |
65 |
66 |
67 |
68 | <% if ((i+1)/4.0).to_i == ((i+1)/4.0) %>
69 |
70 |
71 |
72 | <% end %>
73 |
74 | <% end %>
75 |
76 |
77 | <% unless !@use_paging.nil? and @use_paging==false %>
78 |
79 |
80 | <%= will_paginate @threads %>
81 |
82 |
83 | <% end %>
84 |
85 | <% else %>
86 |
87 |
There are no threads.
88 |
89 | <% end %>
90 |
91 |
92 |
93 |
94 |
106 |
--------------------------------------------------------------------------------
/app/views/home/about.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "About - PageOneX" %>
2 |
3 |
About PageOneX
4 |
<%= image_tag("detail-front-pages.png") %>
5 |
PageOneX is an open source software tool designed to aid the coding, analysis, and visualization of front page newspaper coverage of major stories and media events. Newsrooms spend massive time and effort deciding which stories make it to the front page. Communication scholars have long used column-inches of print newspaper coverage as an important indicator of mass media attention.
6 |
In the past, this approach involved obtaining copies of newspapers, measurement by hand (with a physical ruler), and manual input of measurements into a spreadsheet or database, followed by calculation and analysis. Some of these steps can now be automated, while others can be simplified; some can be easily shared by distributed teams of investigators working with a common dataset hosted online.
7 |
8 |
You can find more information at pageonex.com , examples of PageOnex in use , or the timeline of the project .
9 |
10 |
Background
11 |
The project has gone through different phases.
12 |
Initially , this type of data visualization was made through a ‘manual’ process : images of newspaper front pages were downloaded from the web and reorganized in a vector graphics program to draw rectangles on top of them to highlight certain stories.
13 |
14 |
The first version of an automated tool was a script written in Processing , that downloaded newspapers front pages and generated an organized array of images ordered by date.
15 |
16 |
The second version is this tool written in Ruby on Rails that you are using . It is developed to be a web platform to provide a ready to use front page analysis tool for anyone with a connection to the Internet. The platform automates the process of newspaper selection, download, thread coding, and data visualization. The alpha version was developed by Pablo Rey Mazón with Ahmd Refat , thanks to Google Summer of Code program (GSOC) and the Berkman Center as host institution in Summer 2012. You can test the alpha version at PageOneX.com .
17 |
18 |
In Winter-Spring 2013, at the Center for Civic Media at MIT Media Lab Pablo Rey Mazón, with Edward L Platt and Rahul Bhargava worked on the beta version, the first stable version, that was released on April 2013. It has major improvements in speed and a cleaner data model. During Summer 2013 we were fixing bugs and making the tool work better and faster.
19 |
20 |
During 2014 we've made some improvements like making available to embed a PageOneX in your site or switching on and off topics in the data visualization . We need your feedback! .
21 |
22 |
In Summer 2014 PageOneX won the 2014 APSA-ITP (American Political Science Association-information technology and politics) award for Best Software.
23 |
24 |
Collaborators
25 |
The project has many collaborators. The coders have been/are: initially Ahmd Refat , and now developed at the Center for Civic Media by Edward L Platt , Rahul Bhargava and Pablo Rey Mazón ; Rafael Porres has developed part of the original scraping code. Sasha Costanza-Chock is giving advice and support from the Center for Civic Media; Alfonso Sánchez Uzábal is providing tecnical support and Montera34 helped with the server and domains. Thanks to Jeff Warren for his advice and Rogelio López for testing.
26 |
27 |
Join the project
28 |
Join the mailing list for developers , for users or subscribe to the newsletter to get the last updates.
29 |
30 |
Code
31 |
The code of PageOneX is open source and available at https://github.com/numeroteca/pageonex .
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/views/home/index.html.erb:
--------------------------------------------------------------------------------
1 | <% @title = "PageOneX" %>
2 |
9 |
10 |
11 |
12 |
13 | <%= image_tag "header-blog-2.png", :style => "margin-bottom:5px;" %>
14 |
PageOneX makes it easy to track, code, and visualize major news stories based on the proportion of newspaper front pages that they take up. It's a useful tool for researchers, advocacy groups, and anyone interested in better understanding the media's priorities.
15 |
21 |
22 |
23 |
24 | <% if user_signed_in? %>
25 | <%= link_to 'Create New Thread', '/threads/new', :class => "btn btn-success btn-large" %>
26 | <% else %>
27 | <%= link_to 'Sign in', new_user_session_path, :class => "btn btn-success btn-large" %>
28 | <%= link_to 'Sign up', new_user_registration_path, :class => "btn btn-info btn-large" %>
29 |
30 | <% end %>
31 |
Most recent threads
32 | <% if @threads != [] %>
33 | <% @threads.each do |thread| %>
34 | <% if thread.coded_image_ids.length > 4 %>
35 |
37 | <% end %>
38 | <% end %>
39 | <% else %>
40 |
There are no threads.
41 | <% end %>
42 |
View All
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
67 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------