first commit, largely copied volunteers
|
@ -0,0 +1,7 @@
|
|||
# See https://git-scm.com/docs/gitattributes for more about git attribute files.
|
||||
|
||||
# Mark the database schema as having been generated.
|
||||
db/schema.rb linguist-generated
|
||||
|
||||
# Mark any vendored files as having been vendored.
|
||||
vendor/* linguist-vendored
|
|
@ -0,0 +1,36 @@
|
|||
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
||||
#
|
||||
# If you find yourself ignoring temporary files generated by your text editor
|
||||
# or operating system, you probably want to add a global ignore instead:
|
||||
# git config --global core.excludesfile '~/.gitignore_global'
|
||||
|
||||
# Ignore bundler config.
|
||||
/.bundle
|
||||
|
||||
# Ignore all logfiles and tempfiles.
|
||||
/log/*
|
||||
/tmp/*
|
||||
!/log/.keep
|
||||
!/tmp/.keep
|
||||
|
||||
# Ignore pidfiles, but keep the directory.
|
||||
/tmp/pids/*
|
||||
!/tmp/pids/
|
||||
!/tmp/pids/.keep
|
||||
|
||||
# Ignore uploaded files in development.
|
||||
/storage/*
|
||||
!/storage/.keep
|
||||
/tmp/storage/*
|
||||
!/tmp/storage/
|
||||
!/tmp/storage/.keep
|
||||
/public/uploads
|
||||
|
||||
/public/assets
|
||||
|
||||
# Ignore master key for decrypting credentials and more.
|
||||
/config/master.key
|
||||
nohup.out
|
||||
|
||||
/app/assets/builds/*
|
||||
!/app/assets/builds/.keep
|
|
@ -0,0 +1 @@
|
|||
3.1.3
|
|
@ -0,0 +1,57 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
ruby "3.1.3"
|
||||
|
||||
gem "merged" , git: "https://github.com/FeenixMakers/merged"
|
||||
#gem "merged" , path: "../merged"
|
||||
|
||||
gem "rails", "~> 7.0.0"
|
||||
|
||||
gem "sprockets-rails"
|
||||
|
||||
gem "pg", "~> 1.1"
|
||||
|
||||
gem "importmap-rails"
|
||||
gem "tailwindcss-rails"
|
||||
gem "sassc-rails"
|
||||
|
||||
gem 'haml-rails'
|
||||
gem 'html2haml'
|
||||
gem 'devise'
|
||||
gem 'carrierwave', '>= 3.0.0.beta', '< 4.0'
|
||||
|
||||
gem "ruby2js" , git: "https://github.com/ruby2js/ruby2js/" , branch: "haml_fix"
|
||||
gem 'thredded', '~> 1.0'
|
||||
|
||||
gem "simple_form" , "5.1.0"
|
||||
gem "simple_form_tailwind_css"
|
||||
gem 'kaminari'
|
||||
gem 'ransack'
|
||||
gem "devise-async"
|
||||
|
||||
gem "passenger" , "6.0.15" , require: "phusion_passenger/rack_handler"
|
||||
gem "bootsnap", require: false
|
||||
|
||||
group :development, :test do
|
||||
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
||||
gem "debug", platforms: %i[ mri mingw x64_mingw ]
|
||||
gem 'guard-minitest'
|
||||
gem 'guard' # NOTE: this is necessary in newer versions
|
||||
end
|
||||
|
||||
group :development do
|
||||
# Use console on exceptions pages [https://github.com/rails/web-console]
|
||||
gem "web-console"
|
||||
gem "mina"
|
||||
end
|
||||
|
||||
group :test do
|
||||
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
|
||||
gem "capybara"
|
||||
gem "selenium-webdriver"
|
||||
gem "webdrivers"
|
||||
end
|
||||
|
||||
gem "pundit", "~> 2.3"
|
||||
|
||||
gem "sucker_punch", "~> 3.1"
|
|
@ -0,0 +1,457 @@
|
|||
GIT
|
||||
remote: https://github.com/FeenixMakers/merged
|
||||
revision: 9f6b5a878a36edbb267fe51debd5edc3c1634b81
|
||||
specs:
|
||||
merged (0.1.0)
|
||||
active_hash
|
||||
haml-rails
|
||||
mini_magick
|
||||
rails (>= 7.0.4)
|
||||
redcarpet
|
||||
ruby2js (~> 5.0, >= 5.0.1)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/ruby2js/ruby2js/
|
||||
revision: f204f4e8f14cde6e4d4c6aafc55251a8d488a78d
|
||||
branch: haml_fix
|
||||
specs:
|
||||
ruby2js (5.0.1)
|
||||
parser
|
||||
regexp_parser (~> 2.1.1)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
rack (~> 2.0, >= 2.2.4)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
active_hash (3.2.1)
|
||||
activesupport (>= 5.0.0)
|
||||
active_record_union (1.3.0)
|
||||
activerecord (>= 4.0)
|
||||
activejob (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activerecord (7.0.8)
|
||||
activemodel (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activestorage (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.8)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
addressable (2.8.5)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
ast (2.4.2)
|
||||
autoprefixer-rails (10.4.7.0)
|
||||
execjs (~> 2)
|
||||
babel-source (5.8.35)
|
||||
babel-transpiler (0.7.0)
|
||||
babel-source (>= 4.0, < 6)
|
||||
execjs (~> 2.0)
|
||||
bcrypt (3.1.18)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.15.0)
|
||||
msgpack (~> 1.2)
|
||||
builder (3.2.4)
|
||||
capybara (3.38.0)
|
||||
addressable
|
||||
matrix
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (~> 1.8)
|
||||
rack (>= 1.6.0)
|
||||
rack-test (>= 0.6.3)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
carrierwave (3.0.0.beta)
|
||||
activemodel (>= 6.0.0)
|
||||
activesupport (>= 6.0.0)
|
||||
addressable (~> 2.6)
|
||||
image_processing (~> 1.1)
|
||||
marcel (~> 1.0.0)
|
||||
ssrf_filter (~> 1.0)
|
||||
coderay (1.1.3)
|
||||
concurrent-ruby (1.2.2)
|
||||
crass (1.0.6)
|
||||
date (3.3.3)
|
||||
db_text_search (1.0.0)
|
||||
activerecord (>= 4.1.15)
|
||||
debug (1.7.0)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
devise (4.8.1)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 4.1.0)
|
||||
responders
|
||||
warden (~> 1.2.3)
|
||||
devise-async (1.0.0)
|
||||
activejob (>= 5.0)
|
||||
devise (>= 4.0)
|
||||
erubi (1.12.0)
|
||||
erubis (2.7.0)
|
||||
execjs (2.8.1)
|
||||
ffi (1.15.5)
|
||||
formatador (1.1.0)
|
||||
friendly_id (5.5.0)
|
||||
activerecord (>= 4.0.0)
|
||||
globalid (1.2.1)
|
||||
activesupport (>= 6.1)
|
||||
guard (2.18.0)
|
||||
formatador (>= 0.2.4)
|
||||
listen (>= 2.7, < 4.0)
|
||||
lumberjack (>= 1.0.12, < 2.0)
|
||||
nenv (~> 0.1)
|
||||
notiffany (~> 0.0)
|
||||
pry (>= 0.13.0)
|
||||
shellany (~> 0.0)
|
||||
thor (>= 0.18.1)
|
||||
guard-compat (1.2.1)
|
||||
guard-minitest (2.4.6)
|
||||
guard-compat (~> 1.2)
|
||||
minitest (>= 3.0)
|
||||
haml (6.2.3)
|
||||
temple (>= 0.8.2)
|
||||
thor
|
||||
tilt
|
||||
haml-rails (2.1.0)
|
||||
actionpack (>= 5.1)
|
||||
activesupport (>= 5.1)
|
||||
haml (>= 4.0.6)
|
||||
railties (>= 5.1)
|
||||
heroicon (1.0.0)
|
||||
rails (>= 5.2)
|
||||
html-pipeline (2.14.3)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
html2haml (2.3.0)
|
||||
erubis (~> 2.7.0)
|
||||
haml (>= 4.0)
|
||||
nokogiri (>= 1.6.0)
|
||||
ruby_parser (~> 3.5)
|
||||
htmlentities (4.3.4)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
importmap-rails (1.1.5)
|
||||
actionpack (>= 6.0.0)
|
||||
railties (>= 6.0.0)
|
||||
inline_svg (1.8.0)
|
||||
activesupport (>= 3.0)
|
||||
nokogiri (>= 1.6)
|
||||
io-console (0.6.0)
|
||||
irb (1.6.1)
|
||||
reline (>= 0.3.0)
|
||||
kaminari (1.2.2)
|
||||
activesupport (>= 4.1.0)
|
||||
kaminari-actionview (= 1.2.2)
|
||||
kaminari-activerecord (= 1.2.2)
|
||||
kaminari-core (= 1.2.2)
|
||||
kaminari-actionview (1.2.2)
|
||||
actionview
|
||||
kaminari-core (= 1.2.2)
|
||||
kaminari-activerecord (1.2.2)
|
||||
activerecord
|
||||
kaminari-core (= 1.2.2)
|
||||
kaminari-core (1.2.2)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
listen (3.7.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.21.4)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
lumberjack (1.2.8)
|
||||
mail (2.8.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
marcel (1.0.2)
|
||||
matrix (0.4.2)
|
||||
method_source (1.0.0)
|
||||
mina (1.2.4)
|
||||
open4 (~> 1.3.4)
|
||||
rake
|
||||
mini_magick (4.12.0)
|
||||
mini_mime (1.1.5)
|
||||
minitest (5.20.0)
|
||||
msgpack (1.6.0)
|
||||
multi_json (1.15.0)
|
||||
mustache (1.1.1)
|
||||
nenv (0.3.0)
|
||||
net-imap (0.4.2)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.1)
|
||||
timeout
|
||||
net-smtp (0.4.0)
|
||||
net-protocol
|
||||
nio4r (2.5.9)
|
||||
nokogiri (1.15.4-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
notiffany (0.1.3)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
onebox (2.2.19)
|
||||
addressable (~> 2.8.0)
|
||||
htmlentities (~> 4.3)
|
||||
multi_json (~> 1.11)
|
||||
mustache
|
||||
nokogiri (~> 1.7)
|
||||
sanitize
|
||||
open4 (1.3.4)
|
||||
orm_adapter (0.5.0)
|
||||
parser (3.2.2.4)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
passenger (6.0.15)
|
||||
rack
|
||||
rake (>= 0.8.1)
|
||||
pg (1.4.5)
|
||||
pry (0.14.1)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
public_suffix (5.0.3)
|
||||
pundit (2.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
racc (1.7.1)
|
||||
rack (2.2.8)
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rails (7.0.8)
|
||||
actioncable (= 7.0.8)
|
||||
actionmailbox (= 7.0.8)
|
||||
actionmailer (= 7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
actiontext (= 7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activemodel (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.8)
|
||||
rails-dom-testing (2.2.0)
|
||||
activesupport (>= 5.0.0)
|
||||
minitest
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.6.0)
|
||||
loofah (~> 2.21)
|
||||
nokogiri (~> 1.14)
|
||||
rails_gravatar (1.0.4)
|
||||
actionview
|
||||
railties (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
method_source
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
zeitwerk (~> 2.5)
|
||||
rake (13.0.6)
|
||||
ransack (3.2.1)
|
||||
activerecord (>= 6.1.5)
|
||||
activesupport (>= 6.1.5)
|
||||
i18n
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
redcarpet (3.6.0)
|
||||
regexp_parser (2.1.1)
|
||||
reline (0.3.2)
|
||||
io-console (~> 0.5)
|
||||
responders (3.0.1)
|
||||
actionpack (>= 5.0)
|
||||
railties (>= 5.0)
|
||||
rexml (3.2.5)
|
||||
rinku (2.0.6)
|
||||
ruby-vips (2.1.4)
|
||||
ffi (~> 1.12)
|
||||
ruby_parser (3.19.2)
|
||||
sexp_processor (~> 4.16)
|
||||
rubyzip (2.3.2)
|
||||
sanitize (6.0.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
sassc (2.4.0)
|
||||
ffi (~> 1.9)
|
||||
sassc-rails (2.1.2)
|
||||
railties (>= 4.0.0)
|
||||
sassc (>= 2.0)
|
||||
sprockets (> 3.0)
|
||||
sprockets-rails
|
||||
tilt
|
||||
selenium-webdriver (4.7.1)
|
||||
rexml (~> 3.2, >= 3.2.5)
|
||||
rubyzip (>= 1.2.2, < 3.0)
|
||||
websocket (~> 1.0)
|
||||
sexp_processor (4.16.1)
|
||||
shellany (0.0.1)
|
||||
simple_form (5.1.0)
|
||||
actionpack (>= 5.2)
|
||||
activemodel (>= 5.2)
|
||||
simple_form_tailwind_css (1.0.0)
|
||||
heroicon
|
||||
simple_form
|
||||
sprockets (4.2.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (>= 2.2.4, < 4)
|
||||
sprockets-es6 (0.9.2)
|
||||
babel-source (>= 5.8.11)
|
||||
babel-transpiler
|
||||
sprockets (>= 3.0.0)
|
||||
sprockets-rails (3.4.2)
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
sprockets (>= 3.0.0)
|
||||
ssrf_filter (1.1.1)
|
||||
sucker_punch (3.1.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
tailwindcss-rails (2.0.21-x86_64-linux)
|
||||
railties (>= 6.0.0)
|
||||
temple (0.10.3)
|
||||
thor (1.3.0)
|
||||
thredded (1.0.1)
|
||||
active_record_union (>= 1.3.0)
|
||||
autoprefixer-rails
|
||||
db_text_search
|
||||
friendly_id
|
||||
html-pipeline
|
||||
htmlentities
|
||||
inline_svg (>= 1.6.0)
|
||||
kaminari
|
||||
kramdown (>= 2.0.0)
|
||||
kramdown-parser-gfm
|
||||
nokogiri
|
||||
onebox (>= 1.8.99)
|
||||
pundit (>= 1.1.0)
|
||||
rails (>= 5.2.0, != 6.0.0.rc2)
|
||||
rails_gravatar
|
||||
rinku
|
||||
sanitize
|
||||
sassc-rails (>= 2.0.0)
|
||||
sprockets-es6
|
||||
timeago_js (>= 3.0.2.2)
|
||||
tilt (2.3.0)
|
||||
timeago_js (3.0.2.2)
|
||||
timeout (0.4.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
web-console (4.2.0)
|
||||
actionview (>= 6.0.0)
|
||||
activemodel (>= 6.0.0)
|
||||
bindex (>= 0.4.0)
|
||||
railties (>= 6.0.0)
|
||||
webdrivers (5.2.0)
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (>= 1.3.0)
|
||||
selenium-webdriver (~> 4.0)
|
||||
websocket (1.2.9)
|
||||
websocket-driver (0.7.6)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.12)
|
||||
|
||||
PLATFORMS
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
bootsnap
|
||||
capybara
|
||||
carrierwave (>= 3.0.0.beta, < 4.0)
|
||||
debug
|
||||
devise
|
||||
devise-async
|
||||
guard
|
||||
guard-minitest
|
||||
haml-rails
|
||||
html2haml
|
||||
importmap-rails
|
||||
kaminari
|
||||
merged!
|
||||
mina
|
||||
passenger (= 6.0.15)
|
||||
pg (~> 1.1)
|
||||
pundit (~> 2.3)
|
||||
rails (~> 7.0.0)
|
||||
ransack
|
||||
ruby2js!
|
||||
sassc-rails
|
||||
selenium-webdriver
|
||||
simple_form (= 5.1.0)
|
||||
simple_form_tailwind_css
|
||||
sprockets-rails
|
||||
sucker_punch (~> 3.1)
|
||||
tailwindcss-rails
|
||||
thredded (~> 1.0)
|
||||
web-console
|
||||
webdrivers
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.3p185
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.26
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
guard :minitest do
|
||||
# with Minitest::Unit
|
||||
watch(%r{^test/(.*)\/?(.*)_test\.rb$})
|
||||
watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
|
||||
watch(%r{^test/test_helper\.rb$}) { 'test' }
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
web: bin/rails server -p 3000
|
||||
css: bin/rails tailwindcss:watch
|
|
@ -0,0 +1,24 @@
|
|||
# README
|
||||
|
||||
This README would normally document whatever steps are necessary to get the
|
||||
application up and running.
|
||||
|
||||
Things you may want to cover:
|
||||
|
||||
* Ruby version
|
||||
|
||||
* System dependencies
|
||||
|
||||
* Configuration
|
||||
|
||||
* Database creation
|
||||
|
||||
* Database initialization
|
||||
|
||||
* How to run the test suite
|
||||
|
||||
* Services (job queues, cache servers, search engines, etc.)
|
||||
|
||||
* Deployment instructions
|
||||
|
||||
* ...
|
|
@ -0,0 +1,6 @@
|
|||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
||||
|
||||
require_relative "config/application"
|
||||
|
||||
Rails.application.load_tasks
|
|
@ -0,0 +1,4 @@
|
|||
//= link_tree ../images
|
||||
//= link_directory ../stylesheets .css
|
||||
//= link_tree ../../javascript .js
|
||||
//= link_tree ../builds
|
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1014 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 1021 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 534 KiB |
After Width: | Height: | Size: 612 KiB |
After Width: | Height: | Size: 204 KiB |
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
||||
* listed below.
|
||||
*
|
||||
* Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
|
||||
* vendor/assets/stylesheets directory can be referenced here using a relative path.
|
||||
*
|
||||
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
||||
* compiled file so the styles you add here take precedence over styles defined in any other CSS
|
||||
* files in this directory. Styles in this file should be added after the last require_* statement.
|
||||
* It is generally better to create a new file per style scope.
|
||||
*
|
||||
*= require_self
|
||||
*= require glightbox.min
|
||||
*/
|
||||
#thredded--container{
|
||||
max-width: 60rem;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
@import "tailwind_base";
|
||||
@import "merged_tailwind_styles";
|
|
@ -0,0 +1 @@
|
|||
.glightbox-container{width:100%;height:100%;position:fixed;top:0;left:0;z-index:999999!important;overflow:hidden;-ms-touch-action:none;touch-action:none;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;outline:0}.glightbox-container.inactive{display:none}.glightbox-container .gcontainer{position:relative;width:100%;height:100%;z-index:9999;overflow:hidden}.glightbox-container .gslider{-webkit-transition:-webkit-transform .4s ease;transition:-webkit-transform .4s ease;transition:transform .4s ease;transition:transform .4s ease,-webkit-transform .4s ease;height:100%;left:0;top:0;width:100%;position:relative;overflow:hidden;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.glightbox-container .gslide{width:100%;position:absolute;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;opacity:0}.glightbox-container .gslide.current{opacity:1;z-index:99999;position:relative}.glightbox-container .gslide.prev{opacity:1;z-index:9999}.glightbox-container .gslide-inner-content{width:100%}.glightbox-container .ginner-container{position:relative;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-width:100%;margin:auto;height:100vh}.glightbox-container .ginner-container.gvideo-container{width:100%}.glightbox-container .ginner-container.desc-bottom,.glightbox-container .ginner-container.desc-top{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.glightbox-container .ginner-container.desc-left,.glightbox-container .ginner-container.desc-right{max-width:100%!important}.gslide iframe,.gslide video{outline:0!important;border:none;min-height:165px;-webkit-overflow-scrolling:touch;-ms-touch-action:auto;touch-action:auto}.gslide:not(.current){pointer-events:none}.gslide-image{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.gslide-image img{max-height:100vh;display:block;padding:0;float:none;outline:0;border:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;max-width:100vw;width:auto;height:auto;-o-object-fit:cover;object-fit:cover;-ms-touch-action:none;touch-action:none;margin:auto;min-width:200px}.desc-bottom .gslide-image img,.desc-top .gslide-image img{width:auto}.desc-left .gslide-image img,.desc-right .gslide-image img{width:auto;max-width:100%}.gslide-image img.zoomable{position:relative}.gslide-image img.dragging{cursor:-webkit-grabbing!important;cursor:grabbing!important;-webkit-transition:none;transition:none}.gslide-video{position:relative;max-width:100vh;width:100%!important}.gslide-video .plyr__poster-enabled.plyr--loading .plyr__poster{display:none}.gslide-video .gvideo-wrapper{width:100%;margin:auto}.gslide-video::before{content:'';position:absolute;width:100%;height:100%;background:rgba(255,0,0,.34);display:none}.gslide-video.playing::before{display:none}.gslide-video.fullscreen{max-width:100%!important;min-width:100%;height:75vh}.gslide-video.fullscreen video{max-width:100%!important;width:100%!important}.gslide-inline{background:#fff;text-align:left;max-height:calc(100vh - 40px);overflow:auto;max-width:100%;margin:auto}.gslide-inline .ginlined-content{padding:20px;width:100%}.gslide-inline .dragging{cursor:-webkit-grabbing!important;cursor:grabbing!important;-webkit-transition:none;transition:none}.ginlined-content{overflow:auto;display:block!important;opacity:1}.gslide-external{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;min-width:100%;background:#fff;padding:0;overflow:auto;max-height:75vh;height:100%}.gslide-media{display:-webkit-box;display:-ms-flexbox;display:flex;width:auto}.zoomed .gslide-media{-webkit-box-shadow:none!important;box-shadow:none!important}.desc-bottom .gslide-media,.desc-top .gslide-media{margin:0 auto;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.gslide-description{position:relative;-webkit-box-flex:1;-ms-flex:1 0 100%;flex:1 0 100%}.gslide-description.description-left,.gslide-description.description-right{max-width:100%}.gslide-description.description-bottom,.gslide-description.description-top{margin:0 auto;width:100%}.gslide-description p{margin-bottom:12px}.gslide-description p:last-child{margin-bottom:0}.zoomed .gslide-description{display:none}.glightbox-button-hidden{display:none}.glightbox-mobile .glightbox-container .gslide-description{height:auto!important;width:100%;position:absolute;bottom:0;padding:19px 11px;max-width:100vw!important;-webkit-box-ordinal-group:3!important;-ms-flex-order:2!important;order:2!important;max-height:78vh;overflow:auto!important;background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.75)));background:linear-gradient(to bottom,rgba(0,0,0,0) 0,rgba(0,0,0,.75) 100%);-webkit-transition:opacity .3s linear;transition:opacity .3s linear;padding-bottom:50px}.glightbox-mobile .glightbox-container .gslide-title{color:#fff;font-size:1em}.glightbox-mobile .glightbox-container .gslide-desc{color:#a1a1a1}.glightbox-mobile .glightbox-container .gslide-desc a{color:#fff;font-weight:700}.glightbox-mobile .glightbox-container .gslide-desc *{color:inherit}.glightbox-mobile .glightbox-container .gslide-desc .desc-more{color:#fff;opacity:.4}.gdesc-open .gslide-media{-webkit-transition:opacity .5s ease;transition:opacity .5s ease;opacity:.4}.gdesc-open .gdesc-inner{padding-bottom:30px}.gdesc-closed .gslide-media{-webkit-transition:opacity .5s ease;transition:opacity .5s ease;opacity:1}.greset{-webkit-transition:all .3s ease;transition:all .3s ease}.gabsolute{position:absolute}.grelative{position:relative}.glightbox-desc{display:none!important}.glightbox-open{overflow:hidden}.gloader{height:25px;width:25px;-webkit-animation:lightboxLoader .8s infinite linear;animation:lightboxLoader .8s infinite linear;border:2px solid #fff;border-right-color:transparent;border-radius:50%;position:absolute;display:block;z-index:9999;left:0;right:0;margin:0 auto;top:47%}.goverlay{width:100%;height:calc(100vh + 1px);position:fixed;top:-1px;left:0;background:#000;will-change:opacity}.glightbox-mobile .goverlay{background:#000}.gclose,.gnext,.gprev{z-index:99999;cursor:pointer;width:26px;height:44px;border:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.gclose svg,.gnext svg,.gprev svg{display:block;width:25px;height:auto;margin:0;padding:0}.gclose.disabled,.gnext.disabled,.gprev.disabled{opacity:.1}.gclose .garrow,.gnext .garrow,.gprev .garrow{stroke:#fff}.gbtn.focused{outline:2px solid #0f3d81}iframe.wait-autoplay{opacity:0}.glightbox-closing .gclose,.glightbox-closing .gnext,.glightbox-closing .gprev{opacity:0!important}.glightbox-clean .gslide-description{background:#fff}.glightbox-clean .gdesc-inner{padding:22px 20px}.glightbox-clean .gslide-title{font-size:1em;font-weight:400;font-family:arial;color:#000;margin-bottom:19px;line-height:1.4em}.glightbox-clean .gslide-desc{font-size:.86em;margin-bottom:0;font-family:arial;line-height:1.4em}.glightbox-clean .gslide-video{background:#000}.glightbox-clean .gclose,.glightbox-clean .gnext,.glightbox-clean .gprev{background-color:rgba(0,0,0,.75);border-radius:4px}.glightbox-clean .gclose path,.glightbox-clean .gnext path,.glightbox-clean .gprev path{fill:#fff}.glightbox-clean .gprev{position:absolute;top:-100%;left:30px;width:40px;height:50px}.glightbox-clean .gnext{position:absolute;top:-100%;right:30px;width:40px;height:50px}.glightbox-clean .gclose{width:35px;height:35px;top:15px;right:10px;position:absolute}.glightbox-clean .gclose svg{width:18px;height:auto}.glightbox-clean .gclose:hover{opacity:1}.gfadeIn{-webkit-animation:gfadeIn .5s ease;animation:gfadeIn .5s ease}.gfadeOut{-webkit-animation:gfadeOut .5s ease;animation:gfadeOut .5s ease}.gslideOutLeft{-webkit-animation:gslideOutLeft .3s ease;animation:gslideOutLeft .3s ease}.gslideInLeft{-webkit-animation:gslideInLeft .3s ease;animation:gslideInLeft .3s ease}.gslideOutRight{-webkit-animation:gslideOutRight .3s ease;animation:gslideOutRight .3s ease}.gslideInRight{-webkit-animation:gslideInRight .3s ease;animation:gslideInRight .3s ease}.gzoomIn{-webkit-animation:gzoomIn .5s ease;animation:gzoomIn .5s ease}.gzoomOut{-webkit-animation:gzoomOut .5s ease;animation:gzoomOut .5s ease}@-webkit-keyframes lightboxLoader{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes lightboxLoader{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes gfadeIn{from{opacity:0}to{opacity:1}}@keyframes gfadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes gfadeOut{from{opacity:1}to{opacity:0}}@keyframes gfadeOut{from{opacity:1}to{opacity:0}}@-webkit-keyframes gslideInLeft{from{opacity:0;-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0)}to{visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes gslideInLeft{from{opacity:0;-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0)}to{visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes gslideOutLeft{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0);opacity:0;visibility:hidden}}@keyframes gslideOutLeft{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0);opacity:0;visibility:hidden}}@-webkit-keyframes gslideInRight{from{opacity:0;visibility:visible;-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes gslideInRight{from{opacity:0;visibility:visible;-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes gslideOutRight{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0);opacity:0}}@keyframes gslideOutRight{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0);opacity:0}}@-webkit-keyframes gzoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:1}}@keyframes gzoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:1}}@-webkit-keyframes gzoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}@keyframes gzoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}@media (min-width:769px){.glightbox-container .ginner-container{width:auto;height:auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.glightbox-container .ginner-container.desc-top .gslide-description{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.glightbox-container .ginner-container.desc-top .gslide-image,.glightbox-container .ginner-container.desc-top .gslide-image img{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.glightbox-container .ginner-container.desc-left .gslide-description{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.glightbox-container .ginner-container.desc-left .gslide-image{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.gslide-image img{max-height:97vh;max-width:100%}.gslide-image img.zoomable{cursor:-webkit-zoom-in;cursor:zoom-in}.zoomed .gslide-image img.zoomable{cursor:-webkit-grab;cursor:grab}.gslide-inline{max-height:95vh}.gslide-external{max-height:100vh}.gslide-description.description-left,.gslide-description.description-right{max-width:275px}.glightbox-open{height:auto}.goverlay{background:rgba(0,0,0,.92)}.glightbox-clean .gslide-media{-webkit-box-shadow:1px 2px 9px 0 rgba(0,0,0,.65);box-shadow:1px 2px 9px 0 rgba(0,0,0,.65)}.glightbox-clean .description-left .gdesc-inner,.glightbox-clean .description-right .gdesc-inner{position:absolute;height:100%;overflow-y:auto}.glightbox-clean .gclose,.glightbox-clean .gnext,.glightbox-clean .gprev{background-color:rgba(0,0,0,.32)}.glightbox-clean .gclose:hover,.glightbox-clean .gnext:hover,.glightbox-clean .gprev:hover{background-color:rgba(0,0,0,.7)}.glightbox-clean .gprev{top:45%}.glightbox-clean .gnext{top:45%}}@media (min-width:992px){.glightbox-clean .gclose{opacity:.7;right:20px}}@media screen and (max-height:420px){.goverlay{background:#000}}
|
|
@ -0,0 +1,21 @@
|
|||
.prose {
|
||||
max-width: 100%;
|
||||
color: inherit;
|
||||
--tw-prose-bullets: #6b7280;
|
||||
--tw-prose-headings: inherit;
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.button {
|
||||
@apply inline-block rounded-lg px-3 py-2 text-base font-medium border border-gray-500 hover:border-black;
|
||||
}
|
||||
.change {
|
||||
@apply bg-cyan-200;
|
||||
}
|
||||
.remove {
|
||||
@apply bg-red-200;
|
||||
}
|
||||
.action {
|
||||
@apply bg-green-200;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
|
@ -0,0 +1,18 @@
|
|||
class ApplicationController < ActionController::Base
|
||||
before_action :configure_permitted_parameters, if: :devise_controller?
|
||||
|
||||
include Pundit::Authorization
|
||||
alias :current_user :current_member
|
||||
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
||||
|
||||
protected
|
||||
|
||||
def configure_permitted_parameters
|
||||
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
|
||||
end
|
||||
|
||||
def user_not_authorized
|
||||
flash[:alert] = "You are not authorized to perform this action."
|
||||
redirect_back(fallback_location: root_path)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
class MembersController < ApplicationController
|
||||
before_action :set_member, only: %i[ show edit update destroy ]
|
||||
|
||||
# GET /members
|
||||
def index
|
||||
@members = Member.public_scope.
|
||||
page params[:page]
|
||||
end
|
||||
|
||||
def timeline
|
||||
@members = Member.visible_scope.order(:name).page params[:page]
|
||||
end
|
||||
|
||||
# GET /members/1
|
||||
def show
|
||||
end
|
||||
|
||||
# GET /members/1/edit
|
||||
def edit
|
||||
end
|
||||
|
||||
# POST /members
|
||||
def create
|
||||
@member = Member.new(member_params)
|
||||
|
||||
if @member.save
|
||||
redirect_to @member, notice: "Member was successfully created."
|
||||
else
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /members/1
|
||||
def update
|
||||
if @member.update(member_params)
|
||||
redirect_to @member, notice: "Member was successfully updated."
|
||||
else
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /members/1
|
||||
def destroy
|
||||
@member.destroy
|
||||
redirect_to members_url, notice: "Member was successfully destroyed."
|
||||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_member
|
||||
@member = Member.find(params[:id])
|
||||
end
|
||||
|
||||
# Only allow a list of trusted parameters through.
|
||||
def member_params
|
||||
params.require(:member).permit(:name, :public, :bio , :picture,
|
||||
:picture_cache )
|
||||
end
|
||||
end
|
|
@ -0,0 +1,56 @@
|
|||
class PicturesController < ApplicationController
|
||||
before_action :set_picture, only: %i[ show edit update destroy ]
|
||||
|
||||
def index
|
||||
@q = Picture.ransack(params[:q])
|
||||
@q.sorts = 'created_at desc' if @q.sorts.empty?
|
||||
@pictures = @q.result(distinct: true).page( params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def new
|
||||
@picture = Picture.new
|
||||
end
|
||||
|
||||
def edit
|
||||
authorize @picture
|
||||
end
|
||||
|
||||
def create
|
||||
@picture = Picture.new(picture_params)
|
||||
@picture.member = current_member
|
||||
|
||||
if @picture.save
|
||||
redirect_to @picture, notice: "Picture was successfully created."
|
||||
else
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @picture
|
||||
if @picture.update(picture_params)
|
||||
redirect_to @picture, notice: "Picture was successfully updated."
|
||||
else
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @picture
|
||||
@picture.destroy
|
||||
redirect_to pictures_url, notice: "Picture was successfully destroyed."
|
||||
end
|
||||
|
||||
private
|
||||
def set_picture
|
||||
@picture = Picture.find(params[:id])
|
||||
end
|
||||
|
||||
def picture_params
|
||||
params.require(:picture).permit(:picture,:picture_cache ,:text,
|
||||
:happened , :member_id)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RegistrationsController < Devise::RegistrationsController
|
||||
# before_action :configure_sign_up_params, only: [:create]
|
||||
# before_action :configure_account_update_params, only: [:update]
|
||||
prepend_before_action :authenticate_scope!, only: [:edit_email]
|
||||
|
||||
def new
|
||||
build_resource
|
||||
super
|
||||
end
|
||||
|
||||
def create
|
||||
if message = math_check
|
||||
puts message
|
||||
flash.now.alert = message
|
||||
build_resource(sign_up_params)
|
||||
render :new
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def edit_email
|
||||
build_resource
|
||||
end
|
||||
|
||||
def edit
|
||||
build_resource
|
||||
super
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def math_check
|
||||
return "no cheatin" unless bot = params[:bot]
|
||||
return "No food" unless fudder = bot[:fudder]
|
||||
key = fudder.to_i / 2
|
||||
answer = bot[:challenge]
|
||||
return "Plase enter the bot challenge" if answer.blank?
|
||||
if( (2*key + 1).to_s != answer )
|
||||
return "Check the maths, tip, it wasn't #{answer}"
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
# If you have extra params to permit, append them to the sanitizer.
|
||||
# def configure_sign_up_params
|
||||
# devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
|
||||
# end
|
||||
|
||||
# If you have extra params to permit, append them to the sanitizer.
|
||||
# def configure_account_update_params
|
||||
# devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
|
||||
# end
|
||||
|
||||
# The path used after sign up.
|
||||
def after_sign_up_path_for(resource)
|
||||
super(resource)
|
||||
end
|
||||
|
||||
# The path used after sign up for inactive accounts.
|
||||
# def after_inactive_sign_up_path_for(resource)
|
||||
# super(resource)
|
||||
# end
|
||||
end
|
|
@ -0,0 +1,55 @@
|
|||
class StoriesController < ApplicationController
|
||||
before_action :set_story, only: %i[ show edit update destroy ]
|
||||
|
||||
def index
|
||||
@q = Story.ransack(params[:q])
|
||||
@q.sorts = 'created_at desc' if @q.sorts.empty?
|
||||
@stories = @q.result(distinct: true).page( params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def new
|
||||
@story = Story.new
|
||||
end
|
||||
|
||||
def edit
|
||||
authorize @story
|
||||
end
|
||||
|
||||
def create
|
||||
@story = Story.new(story_params)
|
||||
@story.member = current_member
|
||||
|
||||
if @story.save
|
||||
redirect_to @story, notice: "Story was successfully created."
|
||||
else
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @story
|
||||
if @story.update(story_params)
|
||||
redirect_to @story, notice: "Story was successfully updated."
|
||||
else
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @story
|
||||
@story.destroy
|
||||
redirect_to stories_url, notice: "Story was successfully destroyed."
|
||||
end
|
||||
|
||||
private
|
||||
def set_story
|
||||
@story = Story.find(params[:id])
|
||||
end
|
||||
|
||||
def story_params
|
||||
params.require(:story).permit(:picture,:picture_cache, :header, :text, :happened)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
require "redcarpet"
|
||||
|
||||
module ApplicationHelper
|
||||
|
||||
# different template according to the amount of text
|
||||
def render_story(story)
|
||||
return "" unless story
|
||||
puts story.text.length
|
||||
text_length = story.text.length
|
||||
template = "text"
|
||||
template = "half" if text_length < 500
|
||||
template = "pic" if text_length < 300
|
||||
render partial: "stories/#{template}" , locals: {story: story}
|
||||
end
|
||||
|
||||
def prose_classes
|
||||
classes = "prose lg:prose-lg "
|
||||
classes += "prose-headings:text-inherit "
|
||||
{ class: classes }
|
||||
end
|
||||
|
||||
def renderer
|
||||
options = {hard_wrap: true , autolink: true, no_intra_emphasis: true ,
|
||||
safe_links_only: true, no_styles: true ,
|
||||
link_attributes: { target: '_blank' }}
|
||||
html = Redcarpet::Render::HTML.new(options)
|
||||
Redcarpet::Markdown.new(html, options)
|
||||
end
|
||||
|
||||
def markdown(text)
|
||||
return "" if text.blank?
|
||||
text = text.text unless text.is_a?(String)
|
||||
return "" if text.blank?
|
||||
self.renderer.render(text).html_safe
|
||||
end
|
||||
|
||||
def shorten(text , to = 100)
|
||||
return "" if text.blank?
|
||||
"#{text[0..to]} . . . ".html_safe
|
||||
end
|
||||
def main_app
|
||||
Rails.application.routes.url_helpers
|
||||
end
|
||||
|
||||
def button_classes
|
||||
"mr-3 inline-block rounded-lg px-3 py-2 text-md font-medium border border-gray-500"
|
||||
end
|
||||
|
||||
def rows( text )
|
||||
return 5 if text.blank?
|
||||
text = text.text unless text.is_a?(String)
|
||||
return 5 if text.blank?
|
||||
rows = (text.length / 60).to_i
|
||||
return 5 if rows < 5
|
||||
rows
|
||||
end
|
||||
|
||||
def main_menu
|
||||
[["/members" , "Makerspace"],["/stories" , "Stories"], ["/pictures" , "Gallery"],
|
||||
["/volunteering" , "Volunteering"] ]
|
||||
end
|
||||
def member_memu
|
||||
items =[ [main_app.member_path(current_member) , "Settings"]]
|
||||
if !Rails.env.production?
|
||||
items << [merged.pages_path(), "CMS" ]
|
||||
end
|
||||
items
|
||||
end
|
||||
def mobile_menu
|
||||
if current_member
|
||||
member_memu
|
||||
else
|
||||
[main_app.member_session_path, "Login"]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module HeroiconHelper
|
||||
include Heroicon::Engine.helpers
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
module MembersHelper
|
||||
|
||||
def picture_for(someone , classes = "")
|
||||
image = someones_path(someone)
|
||||
if someone.respond_to? :name
|
||||
alt = someone.name
|
||||
else
|
||||
alt = ""
|
||||
end
|
||||
image_tag(image , alt: alt , class: classes )
|
||||
end
|
||||
|
||||
def someones_path( someone )
|
||||
if someone.picture.blank?
|
||||
asset_url("no_image.png")
|
||||
else
|
||||
someone.picture.url
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
module PicturesHelper
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
module StoriesHelper
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
// Configure your import map in config/importmap.rb.
|
||||
// Read more: https://github.com/rails/importmap-rails
|
||||
|
||||
// Currently haml filter does not support modules.
|
||||
// import and make global as workaround
|
||||
//
|
||||
// haml module syntax is really clunky, filing issue and hoping
|
||||
//
|
||||
import GLightbox from 'glightbox';
|
||||
globalThis.GLightbox = GLightbox;
|
|
@ -0,0 +1,7 @@
|
|||
class ApplicationJob < ActiveJob::Base
|
||||
# Automatically retry jobs that encountered a deadlock
|
||||
# retry_on ActiveRecord::Deadlocked
|
||||
|
||||
# Most jobs are safe to ignore if the underlying records are no longer available
|
||||
# discard_on ActiveJob::DeserializationError
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
class ApplicationMailer < ActionMailer::Base
|
||||
default from: "from@example.com"
|
||||
layout "mailer"
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class ApplicationRecord < ActiveRecord::Base
|
||||
primary_abstract_class
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
class Member < ApplicationRecord
|
||||
after_create :skip_conf!
|
||||
|
||||
def self.public_scope
|
||||
where.not(confirmed_at: nil).where.not(picture: nil)
|
||||
end
|
||||
|
||||
def self.visible_scope
|
||||
where.not(confirmed_at: nil)
|
||||
end
|
||||
|
||||
# Include default devise modules. Others available are:
|
||||
# , :lockable, :timeoutable, :trackable and :omniauthable
|
||||
devise :database_authenticatable, :registerable,:confirmable,
|
||||
:recoverable, :rememberable, :validatable, :async
|
||||
|
||||
def skip_conf!
|
||||
self.confirm if Rails.env.development?
|
||||
end
|
||||
|
||||
mount_uploader :picture, PictureUploader
|
||||
has_many :stories
|
||||
has_many :stories
|
||||
has_many :pictures
|
||||
|
||||
validates :bio, length: { maximum: 1000 }
|
||||
validates :name , length: { minimum: 3 }
|
||||
|
||||
def admin
|
||||
self.email == "torsten@villataika.fi"
|
||||
end
|
||||
def admin?
|
||||
self.email == "torsten@villataika.fi"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
class Picture < ApplicationRecord
|
||||
belongs_to :member
|
||||
|
||||
mount_uploader :picture, PictureUploader
|
||||
|
||||
validates :text, length: { maximum: 80 }
|
||||
validates :happened, presence: true
|
||||
validates :picture, presence: true
|
||||
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
class Story < ApplicationRecord
|
||||
belongs_to :member
|
||||
|
||||
mount_uploader :picture, PictureUploader
|
||||
|
||||
validates :text, length: { minimum: 5 , maximum: 1000 }
|
||||
validates :header , length: { minimum: 5 , maximum: 400}
|
||||
validates :picture, presence: true
|
||||
|
||||
def name
|
||||
header
|
||||
end
|
||||
end
|
|
@ -0,0 +1,53 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ApplicationPolicy
|
||||
attr_reader :member, :record
|
||||
|
||||
def initialize(member, record)
|
||||
@member = member
|
||||
@record = record
|
||||
end
|
||||
|
||||
def index?
|
||||
false
|
||||
end
|
||||
|
||||
def show?
|
||||
false
|
||||
end
|
||||
|
||||
def create?
|
||||
false
|
||||
end
|
||||
|
||||
def new?
|
||||
create?
|
||||
end
|
||||
|
||||
def update?
|
||||
false
|
||||
end
|
||||
|
||||
def edit?
|
||||
update?
|
||||
end
|
||||
|
||||
def destroy?
|
||||
false
|
||||
end
|
||||
|
||||
class Scope
|
||||
def initialize(member, scope)
|
||||
@member = member
|
||||
@scope = scope
|
||||
end
|
||||
|
||||
def resolve
|
||||
raise NotImplementedError, "You must define #resolve in #{self.class}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :member, :scope
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
# allows to edit/detroy own data
|
||||
# which can be viewed by anyone
|
||||
class EditOwnPolicy < ApplicationPolicy
|
||||
def edit?
|
||||
return true if member.admin?
|
||||
owner?
|
||||
end
|
||||
def owner?
|
||||
member == record.member
|
||||
end
|
||||
alias :update? :edit?
|
||||
alias :destroy? :edit?
|
||||
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class PicturePolicy < EditOwnPolicy
|
||||
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class StoryPolicy < EditOwnPolicy
|
||||
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
class PictureUploader < CarrierWave::Uploader::Base
|
||||
# Include RMagick or MiniMagick support:
|
||||
# include CarrierWave::RMagick
|
||||
include CarrierWave::MiniMagick
|
||||
|
||||
# Choose what kind of storage to use for this uploader:
|
||||
storage :file
|
||||
# storage :fog
|
||||
|
||||
# Override the directory where uploaded files will be stored.
|
||||
# This is a sensible default for uploaders that are meant to be mounted:
|
||||
def store_dir
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
|
||||
# Provide a default URL as a default if there hasn't been a file uploaded:
|
||||
def default_url(*args)
|
||||
# For Rails 3.1+ asset pipeline compatibility:
|
||||
ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
|
||||
end
|
||||
|
||||
# Process files as they are uploaded:
|
||||
# process scale: [200, 300]
|
||||
#
|
||||
# def scale(width, height)
|
||||
# # do something
|
||||
# end
|
||||
|
||||
# Create different versions of your uploaded files:
|
||||
# version :thumb do
|
||||
# process resize_to_fit: [50, 50]
|
||||
# end
|
||||
|
||||
def content_type_allowlist
|
||||
/image\//
|
||||
end
|
||||
|
||||
# Override the filename of the uploaded files:
|
||||
# Avoid using model.id or version_name here, see uploader/store.rb for details.
|
||||
# def filename
|
||||
# "something.jpg" if original_filename
|
||||
# end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs.md:max-w-md
|
||||
%h1.font-hairline.mb-6.text-center Resend Confirmation Instructions
|
||||
= form_for(resource, as: resource_name,
|
||||
url: confirmation_path(resource_name),
|
||||
html: { class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" ,
|
||||
method: :post }) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
.mb-4
|
||||
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.email_field :email, |
|
||||
autofocus: true, |
|
||||
autocomplete: "email", |
|
||||
value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email), |
|
||||
class: "appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none shadow focus:shadow-outline" |
|
||||
.mb-4
|
||||
= f.submit "Resend Confirmation Info", |
|
||||
class: "button bg-cyan-700 hover:bg-cyan-500 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full" |
|
||||
= render "devise/shared/links"
|
||||
= render "devise/shared/form_footer"
|
|
@ -0,0 +1,14 @@
|
|||
%p
|
||||
Welcome #{@resource.name}!
|
||||
|
||||
%p You can confirm your stay through the link below:
|
||||
%p= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token)
|
||||
|
||||
Remember you can change the dates later, under the Settings.
|
||||
|
||||
You can also set a profile and picture to tell others about yourself.
|
||||
And once at the Hub, you can add pictures and stories to share with others.
|
||||
|
||||
Looking forward to seeing you in person
|
||||
|
||||
The hub team
|
|
@ -0,0 +1,8 @@
|
|||
%p
|
||||
Hello #{@email}!
|
||||
- if @resource.try(:unconfirmed_email?)
|
||||
%p
|
||||
We're contacting you to notify you that your email is being changed to #{@resource.unconfirmed_email}.
|
||||
- else
|
||||
%p
|
||||
We're contacting you to notify you that your email has been changed to #{@resource.email}.
|
|
@ -0,0 +1,3 @@
|
|||
%p
|
||||
Hello #{@resource.email}!
|
||||
%p We're contacting you to notify you that your password has been changed.
|
|
@ -0,0 +1,6 @@
|
|||
%p
|
||||
Hello #{@resource.email}!
|
||||
%p Someone has requested a link to change your password. You can do this through the link below.
|
||||
%p= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token)
|
||||
%p If you didn't request this, please ignore this email.
|
||||
%p Your password won't change until you access the link above and create a new one.
|
|
@ -0,0 +1,5 @@
|
|||
%p
|
||||
Hello #{@resource.email}!
|
||||
%p Your account has been locked due to an excessive number of unsuccessful sign in attempts.
|
||||
%p Click the link below to unlock your account:
|
||||
%p= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token)
|
|
@ -0,0 +1,32 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs.md:max-w-md
|
||||
%h2.font-hairline.mb-6.text-center Change Your Password
|
||||
= form_for(resource,
|
||||
as: resource_name,
|
||||
html: { method: :put, class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" },
|
||||
url: password_path(resource_name) ) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
= f.hidden_field :reset_password_token
|
||||
.mb-4
|
||||
= f.label :password, "New Password",
|
||||
class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
- if @minimum_password_length
|
||||
%small
|
||||
%em.text-gray-600
|
||||
(#{@minimum_password_length} characters minimum)
|
||||
= f.password_field :password, |
|
||||
autofocus: true, |
|
||||
autocomplete: "new-password", |
|
||||
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full"
|
||||
.mb-4
|
||||
= f.label :password_confirmation,
|
||||
"Confirm New Password",
|
||||
class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.password_field :password_confirmation, |
|
||||
autocomplete: "off", |
|
||||
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
|
||||
.mb-4
|
||||
= f.submit "Change My Password", |
|
||||
class: "button bg-cyan-700 hover:bg-cyan-500 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full"
|
||||
= render "devise/shared/links"
|
||||
= render "devise/shared/form_footer"
|
|
@ -0,0 +1,17 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs.md:max-w-md
|
||||
%h1.font-hairline.mb-6.text-center Forgot your password?
|
||||
= form_for(resource, as: resource_name,
|
||||
html: { method: :post,
|
||||
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" } ,
|
||||
url: password_path(resource_name) ) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
.mb-4
|
||||
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.email_field :email, autofocus: true, autocomplete: "email", |
|
||||
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full" |
|
||||
.mb-4
|
||||
= f.submit "Send Password Reset Info", |
|
||||
class: "button bg-cyan-700 hover:bg-cyan-500 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full" |
|
||||
= render "devise/shared/links"
|
||||
= render "devise/shared/form_footer"
|
|
@ -0,0 +1,32 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs.md:max-w-md
|
||||
%h1.font-hairline.mb-6.text-center.text-2xl
|
||||
Change password
|
||||
= form_for(resource, as: resource_name,
|
||||
html: { class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md",
|
||||
method: :put } ,
|
||||
url: registration_path(resource_name) ) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
|
||||
%div
|
||||
Currently waiting confirmation for: #{resource.unconfirmed_email}
|
||||
.mb-4
|
||||
= f.label :new_password, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.password_field :password, autocomplete: "new-password", class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
|
||||
.mb-4
|
||||
= f.label :password_confirmation, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.password_field :password_confirmation, |
|
||||
autocomplete: "new-password", |
|
||||
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" |
|
||||
.mb-4
|
||||
= f.label :current_password, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.password_field :current_password, |
|
||||
autocomplete: "current-password", |
|
||||
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" |
|
||||
.actions
|
||||
= f.submit "Update", class: "button bg-cyan-700 hover:bg-cyan-500 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full"
|
||||
.flex.justify-between
|
||||
%p
|
||||
%span= button_to "Delete my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete , class: button_classes
|
||||
%button{class: button_classes}
|
||||
= link_to "Back", :back
|
|
@ -0,0 +1,32 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs.md:max-w-md
|
||||
%h1.font-hairline.mb-6.text-center.text-2xl
|
||||
Change your email
|
||||
.text-center.text-lg
|
||||
(requires confirmation)
|
||||
= form_for(resource, as: resource_name,
|
||||
html: { class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md",
|
||||
method: :put } ,
|
||||
url: registration_path(resource_name) ) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
.mb-4
|
||||
= f.label :new_email, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
%br/
|
||||
= f.email_field :email, |
|
||||
autofocus: true, |
|
||||
autocomplete: "email", |
|
||||
class: "appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none shadow focus:shadow-outline" |
|
||||
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
|
||||
%div
|
||||
Currently waiting confirmation for: #{resource.unconfirmed_email}
|
||||
.mb-4
|
||||
= f.label :current_password, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.password_field :current_password, |
|
||||
autocomplete: "current-password", |
|
||||
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" |
|
||||
.actions
|
||||
= f.submit "Update", class: "button bg-cyan-700 hover:bg-cyan-500 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full"
|
||||
|
||||
= link_to :back do
|
||||
%button{class: button_classes}
|
||||
Back
|
|
@ -0,0 +1,51 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs.md:max-w-md
|
||||
%h1.font-hairline.mb-6.text-center.text-2xl Confirm your stay
|
||||
= form_for(resource, as: resource_name,
|
||||
html: { class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" } ,
|
||||
url: registration_path(resource_name) ) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
.mb-4
|
||||
Please read the
|
||||
= link_to "house rules" , "/house_rules" , class: "underline"
|
||||
if you haven't yet, and let us know of
|
||||
any alergies (food?) or medical conditions (ADHD?) beforehand.
|
||||
.mb-4
|
||||
= f.label :name, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.input :name,
|
||||
placeholder: "Pekka",
|
||||
class: "appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none shadow focus:shadow-outline"
|
||||
.mb-4
|
||||
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.email_field :email,
|
||||
autocomplete: "email",
|
||||
placeholder: "user@example.com",
|
||||
class: "appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none shadow focus:shadow-outline"
|
||||
.mb-4
|
||||
= f.label :password, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
- if @minimum_password_length
|
||||
%small
|
||||
%em.text-gray-600
|
||||
(#{@minimum_password_length} characters minimum)
|
||||
= f.password_field :password,
|
||||
autocomplete: "new-password",
|
||||
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
|
||||
.mb-4
|
||||
= f.label :password_confirmation, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.password_field :password_confirmation,
|
||||
autocomplete: "new-password",
|
||||
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full"
|
||||
.mt-4
|
||||
- challenge = rand(8)
|
||||
= simple_fields_for :bot do |n|
|
||||
= n.input :fudder , as: :hidden , input_html: { value: "#{challenge*2}" }
|
||||
= n.input :challenge, placeholder: "Anti bot question: #{challenge} + #{challenge + 1} == " ,
|
||||
class: " border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full"
|
||||
.my-4
|
||||
= f.submit "Sign Up",
|
||||
class: "button bg-cyan-700 hover:bg-cyan-700 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full"
|
||||
%p
|
||||
After submitting you will receive a confirmation email.
|
||||
Your place will be ensured once you have confirmed your email.
|
||||
= render "devise/shared/links"
|
||||
= render "devise/shared/form_footer"
|
|
@ -0,0 +1,26 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs.md:max-w-md
|
||||
%h1.font-hairline.mb-6.text-center Log In
|
||||
= form_for(resource, url: session_path(resource_name),
|
||||
html: { class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" },
|
||||
as: resource_name ) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
.mb-4
|
||||
= f.label :email, class: "block text-gray-700 text-sm font-bold mb-2"
|
||||
= f.email_field :email, autofocus: true, autocomplete: "email",
|
||||
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight foucs:outline-none focus:shadow-outline"
|
||||
.mb-4
|
||||
= f.label :password, class: "block text-gray-700 text-sm font-bold mb-2"
|
||||
= f.password_field :password,
|
||||
autocomplete: "current-password",
|
||||
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
||||
- if devise_mapping.rememberable?
|
||||
.mb-4
|
||||
= f.check_box :remember_me, class: "mr-2 leading-tight"
|
||||
= f.label :remember_me,
|
||||
class: "align-baseline inline-block text-gray-700 text-sm"
|
||||
.mb-4
|
||||
= f.submit "Log in",
|
||||
class: "button bg-cyan-700 hover:bg-cyan-500 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full"
|
||||
= render "devise/shared/links"
|
||||
= render "devise/shared/form_footer"
|
|
@ -0,0 +1,9 @@
|
|||
- if resource.errors.any?
|
||||
#error_explanation
|
||||
%h2.bg-red-100.border-l-4.border-red-500.mb-4.p-4.text-red-700.font-bold
|
||||
= I18n.t("errors.messages.not_saved",
|
||||
count: resource.errors.count,
|
||||
resource: resource.class.model_name.human.downcase)
|
||||
%ul
|
||||
- resource.errors.full_messages.each do |message|
|
||||
%li= message
|
|
@ -0,0 +1,2 @@
|
|||
%p.text-center.text-gray-500.text-xs
|
||||
Be a member of Hub Feenix
|
|
@ -0,0 +1,20 @@
|
|||
- if controller_name != 'sessions'
|
||||
= link_to "Log in", new_session_path(resource_name), |
|
||||
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
|
||||
%br/
|
||||
- if devise_mapping.registerable? && controller_name != 'registrations'
|
||||
= link_to "Sign up", new_registration_path(resource_name), |
|
||||
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
|
||||
%br/
|
||||
- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
|
||||
= link_to "Forgot Password?", new_password_path(resource_name), |
|
||||
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
|
||||
%br/
|
||||
- if devise_mapping.confirmable? && controller_name != 'confirmations'
|
||||
= link_to "Didn't receive confirmation info?", new_confirmation_path(resource_name), |
|
||||
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
|
||||
%br/
|
||||
- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
|
||||
= link_to "Didn't receive unlock info?", new_unlock_path(resource_name), |
|
||||
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
|
||||
%br/
|
|
@ -0,0 +1,19 @@
|
|||
.flex.justify-center
|
||||
.w-full.max-w-xs
|
||||
%h1.font-hairline.mb-6.text-center Resend Unlock Info
|
||||
= form_for(resource, as: resource_name,
|
||||
html: { class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" ,
|
||||
method: :post }
|
||||
url: unlock_path(resource_name) ) do |f|
|
||||
= render "devise/shared/error_messages", resource: resource
|
||||
.mb-4
|
||||
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
|
||||
= f.email_field :email, |
|
||||
autofocus: true, |
|
||||
autocomplete: "email", |
|
||||
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full" |
|
||||
.mb-4
|
||||
= f.submit "Resend unlock instructions", |
|
||||
class: "button bg-blue-500 hover:bg-blue-700 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full" |
|
||||
= render "devise/shared/links"
|
||||
= render "devise/shared/form_footer"
|
|
@ -0,0 +1,9 @@
|
|||
-# Link to the "First" page
|
||||
-# available local variables
|
||||
-# url: url to the first page
|
||||
-# current_page: a page object for the currently displayed page
|
||||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
%span.first
|
||||
= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote
|
|
@ -0,0 +1,8 @@
|
|||
-# Non-link tag that stands for skipped pages...
|
||||
-# available local variables
|
||||
-# current_page: a page object for the currently displayed page
|
||||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
%span.page.gap
|
||||
= t('views.pagination.truncate').html_safe
|
|
@ -0,0 +1,9 @@
|
|||
-# Link to the "Last" page
|
||||
-# available local variables
|
||||
-# url: url to the last page
|
||||
-# current_page: a page object for the currently displayed page
|
||||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
%span.last
|
||||
= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote
|
|
@ -0,0 +1,9 @@
|
|||
-# Link to the "Next" page
|
||||
-# available local variables
|
||||
-# url: url to the next page
|
||||
-# current_page: a page object for the currently displayed page
|
||||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
%span.next
|
||||
= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote
|
|
@ -0,0 +1,10 @@
|
|||
-# Link showing page number
|
||||
-# available local variables
|
||||
-# page: a page object for "this" page
|
||||
-# url: url to this page
|
||||
-# current_page: a page object for the currently displayed page
|
||||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
%span{class: "page#{' current' if page.current?}"}
|
||||
= link_to_unless page.current?, page, url, {remote: remote, rel: page.rel}
|
|
@ -0,0 +1,18 @@
|
|||
-# The container tag
|
||||
-# available local variables
|
||||
-# current_page: a page object for the currently displayed page
|
||||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
-# paginator: the paginator that renders the pagination tags inside
|
||||
= paginator.render do
|
||||
%nav.pagination
|
||||
= first_page_tag unless current_page.first?
|
||||
= prev_page_tag unless current_page.first?
|
||||
- each_page do |page|
|
||||
- if page.display_tag?
|
||||
= page_tag page
|
||||
- elsif !page.was_truncated?
|
||||
= gap_tag
|
||||
= next_page_tag unless current_page.last?
|
||||
= last_page_tag unless current_page.last?
|
|
@ -0,0 +1,9 @@
|
|||
-# Link to the "Previous" page
|
||||
-# available local variables
|
||||
-# url: url to the previous page
|
||||
-# current_page: a page object for the currently displayed page
|
||||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
%span.prev
|
||||
= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote
|
|
@ -0,0 +1,112 @@
|
|||
%footer.bg-white{"aria-label" => "Site Footer"}
|
||||
.px-4.py-16.mx-auto.sm:px-6.lg:px-8
|
||||
.w-full.grid.grid-cols-2.gap-8.mt-8.lg:mt-0.lg:grid-cols-6.lg:gap-y-16.ld:grid-cols-3.lg:gap-y-8
|
||||
.max-w-screen-xl.px-4.py-16.mx-auto.sm:px-6.lg:px-8
|
||||
.lg:flex.lg:items-start.lg:gap-8
|
||||
%a.inline-flex.items-center{"aria-label" => "Hub Feenix", :href => "/", :title => "Hub Feenix"}
|
||||
= image_tag("feenix_lintu.webp" , class: "h-20")
|
||||
|
||||
%nav.mt-6
|
||||
%p.mb-6.font-medium.text-xl.text-gray-900
|
||||
Activities
|
||||
%ul.space-y-4.text-sm
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/local_activities"}
|
||||
Local Area
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/helsinki"}
|
||||
Helsinki
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/turku"}
|
||||
Turkku
|
||||
|
||||
%nav.mt-6
|
||||
%p.mb-6.font-medium.text-xl.text-gray-900
|
||||
Weather Info
|
||||
%ul.space-y-4.text-sm
|
||||
%li
|
||||
%a.text-md.transition.hover:opacity-75{:href => "/four_seasons"}
|
||||
Four Seasons
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/in_summer"}
|
||||
In Summer
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/in_winter"}
|
||||
In Winter
|
||||
|
||||
%nav.mt-6{"aria-label" => "Footer Navigation - Hub Feenix"}
|
||||
%p.mb-6.font-medium.text-xl.text-gray-900
|
||||
Volunteering
|
||||
%ul.space-y-4.text-sm
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/volunteering"}
|
||||
About Volunteering
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/arriving"}
|
||||
Getting here
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/living_here"}
|
||||
Living @ Feenix Info
|
||||
|
||||
%nav.mt-6{"aria-label" => "Footer Navigation - Hub Feenix"}
|
||||
%p.mb-6.font-medium.text-xl.text-gray-900
|
||||
People
|
||||
%ul.space-y-4.text-sm
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/members"}
|
||||
Makerspace
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/stories"}
|
||||
Stories
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/pictures"}
|
||||
Gallery
|
||||
|
||||
%nav.mt-6{"aria-label" => "Footer Navigation - Downloads"}
|
||||
%p.mb-6.font-medium.text-xl.text-gray-900
|
||||
Information
|
||||
%ul.space-y-4.text-sm
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "/about"}
|
||||
About Hub Feenix
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "https://www.hubfeenix.fi" , target: :blank }
|
||||
Hub Feenix Website
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "https://www.facebook.com/hubfeenix" , :target => "_blank"}
|
||||
Facebook
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "https://www.instagram.com/hub_feenix/" , :target => "_blank"}
|
||||
Instagram
|
||||
|
||||
%ul.flex.justify-start.col-span-2.gap-6.lg:col-span-5.lg:justify-end
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "https://www.facebook.com/hubfeenix", :rel => "noreferrer", :target => "_blank"}
|
||||
%span.sr-only Facebook
|
||||
%svg.w-6.h-6{"aria-hidden" => "true", :fill => "currentColor", :viewBox => "0 0 24 24"}
|
||||
%path{"clip-rule" => "evenodd", :d => "M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z", "fill-rule" => "evenodd"}
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "https://www.instagram.com/hub_feenix/", :rel => "noreferrer", :target => "_blank"}
|
||||
%span.sr-only Instagram
|
||||
%svg.w-6.h-6{"aria-hidden" => "true", :fill => "currentColor", :viewBox => "0 0 24 24"}
|
||||
%path{"clip-rule" => "evenodd", :d => "M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z", "fill-rule" => "evenodd"}
|
||||
%li
|
||||
%a.text-gray-700.transition.hover:opacity-75{:href => "https://github.com/FeenixMakers", :rel => "noreferrer", :target => "_blank"}
|
||||
%span.sr-only GitHub
|
||||
%svg.w-6.h-6{"aria-hidden" => "true", :fill => "currentColor", :viewBox => "0 0 24 24"}
|
||||
%path{"clip-rule" => "evenodd", :d => "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z", "fill-rule" => "evenodd"}
|
||||
.pt-8.mt-8.border-t.border-gray-100
|
||||
.grid.grid-cols-1.gap-8.lg:grid-cols-2
|
||||
%p.text-xs.text-left.text-gray-500
|
||||
2020-23. Osuuskunta Hub Feenix. All rights reserved.
|
||||
%nav{"aria-label" => "Footer Navigation - Support"}
|
||||
%ul.flex.flex-wrap.justify-start.gap-4.text-xs.lg:justify-end
|
||||
%li
|
||||
%a.text-gray-500.transition.hover:opacity-75{:href => "#"}
|
||||
=#Terms Conditions
|
||||
%li
|
||||
%a.text-gray-500.transition.hover:opacity-75{:href => "#"}
|
||||
=#Privacy Policy
|
||||
%li
|
||||
%a.text-gray-500.transition.hover:opacity-75{:href => "#"}
|
||||
=#Cookies
|
|
@ -0,0 +1,38 @@
|
|||
%header.px-4.py-5.mx-auto.sm:max-w-xl.md:max-w-full.lg:max-w-screen-xl.md:px-24.lg:px-8
|
||||
.relative.flex.items-center.justify-between
|
||||
%a.inline-flex.items-center{"aria-label" => "Hub Feenix", :href => "/", :title => "Hub Feenix"}
|
||||
= image_tag("feenix_lintu.webp" , class: "h-20")
|
||||
%span.ml-2.text-xl.font-bold.text-gray-800 Makerspace @ Hub Feenix
|
||||
%ul.flex.items-center.hidden.space-x-8.lg:flex
|
||||
- main_menu.each do |link , text|
|
||||
%li
|
||||
%a.font-medium.tracking-wide.text-gray-700.transition-colors.duration-400.hover:text-cyan-800{"aria-label" => "Our product", :href => link, :title => text}= text
|
||||
%li
|
||||
= link_to "https://www.facebook.com/hubfeenix" , :target => "_blank" do
|
||||
= image_tag("fb.webp" , class: "h-10 rounded-md")
|
||||
%li
|
||||
- unless member_signed_in?
|
||||
%a.inline-flex.items-center.justify-center.h-12.px-6.font-medium.tracking-wide.text-white.transition.duration-200.rounded-lg.shadow-md.bg-green-800.hover:bg-blue-800.focus:shadow-outline.focus:outline-none{"aria-label" => "Sign up", :href => main_app.member_session_path, :title => "Log in or Sign up"}
|
||||
Login
|
||||
- else
|
||||
.inline-flex.items-stretch.rounded-md.border
|
||||
.rounded-l-md.px-4.py-2.text-sm.text-gray-600.hover:bg-cyan-100.hover:text-gray-900
|
||||
=link_to current_member.email , main_app.member_path(current_member)
|
||||
.relative
|
||||
%button.inline-flex.h-full.items-center.justify-center.rounded-r-md.border-l.border-gray-100.px-2.text-gray-600.hover:bg-cyan-400{:type => "button" , onclick: "dropdown();" }
|
||||
%span.sr-only Menu
|
||||
%svg.h-4.w-4{:fill => "currentColor", :viewbox => "0 0 20 20", :xmlns => "http://www.w3.org/2000/svg"}
|
||||
%path{"clip-rule" => "evenodd", :d => "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", "fill-rule" => "evenodd"}
|
||||
=render "layouts/member_menu"
|
||||
|
||||
.lg:hidden.flex.items-center.justify-between
|
||||
.mr-20
|
||||
= link_to "https://www.facebook.com/hubfeenix" , :target => "_blank" do
|
||||
= image_tag("fb.webp" , class: "h-10 rounded-md")
|
||||
%button.p-2.-mr-1.transition.duration-200.rounded.focus:outline-none.focus:shadow-outline.hover:bg-deep-purple-50.focus:bg-deep-purple-50{"aria-label" => "Open Menu", :title => "Open Menu" , onclick: "menu_on();"}
|
||||
%svg.w-5.text-gray-600{:viewbox => "0 0 24 24"}
|
||||
%path{:d => "M23,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h22c0.6,0,1,0.4,1,1S23.6,13,23,13z", :fill => "currentColor"}
|
||||
%path{:d => "M23,6H1C0.4,6,0,5.6,0,5s0.4-1,1-1h22c0.6,0,1,0.4,1,1S23.6,6,23,6z", :fill => "currentColor"}
|
||||
%path{:d => "M23,20H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h22c0.6,0,1,0.4,1,1S23.6,20,23,20z", :fill => "currentColor"}
|
||||
|
||||
= render "layouts/mobile_menu"
|
|
@ -0,0 +1,23 @@
|
|||
#menu-dropdown.hidden.absolute.right-0.z-10.mt-4.w-36.origin-top-right.rounded-md.border.border-gray-100.bg-white.shadow-lg{:role => "menu"}
|
||||
.p-2
|
||||
- member_memu.each do |link , text|
|
||||
%a.block.rounded-lg.px-4.py-2.text-sm.text-gray-500.hover:bg-gray-50.hover:text-gray-700{:href => link, :role => "menuitem"}
|
||||
=text
|
||||
= form_tag( main_app.destroy_member_session_path , {method: :delete } ) do
|
||||
%button.flex.w-full.items-center.gap-2.rounded-lg.px-4.py-2.text-sm.text-blue-700.hover:bg-red-50{:role => "menuitem", :type => "submit"}
|
||||
%svg.h-4.w-4{:fill => "none", :stroke => "currentColor", "stroke-width" => "2", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
||||
%path{:d => "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
|
||||
Sign out
|
||||
|
||||
:javascript
|
||||
var drop_hidden = true;
|
||||
function dropdown(){
|
||||
var x = document.getElementById("menu-dropdown");
|
||||
if( drop_hidden == true){
|
||||
x.style.display = "block";
|
||||
drop_hidden = false ;
|
||||
} else {
|
||||
x.style.display = "none";
|
||||
drop_hidden = true ;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
-if flash.alert
|
||||
#flash
|
||||
.m-20.rounded.border-l-4.border-red-500.bg-red-50.p-4{:role => "alert"}
|
||||
%strong.block.font-medium.text-red-700 Oops
|
||||
%p.mt-2.text-sm.text-red-700
|
||||
=flash.alert
|
||||
|
||||
-if flash.notice
|
||||
#flash
|
||||
.m-20.rounded-xl.border.border-gray-100.p-4.shadow-xl{:role => "alert"}
|
||||
.flex.items-start.gap-4
|
||||
%span.text-green-600
|
||||
%svg.h-6.w-6{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
||||
%path{:d => "M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
|
||||
.flex-1
|
||||
%strong.block.font-medium.text-gray-900 Ok
|
||||
%p.mt-1.text-sm.text-gray-700
|
||||
= flash.notice
|
||||
:javascript
|
||||
function hideNotice() {
|
||||
const notification = document.querySelector('#flash')
|
||||
if (notification) {
|
||||
setInterval(function() {
|
||||
notification.classList.add('hidden');
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
hideNotice();
|
|
@ -0,0 +1,42 @@
|
|||
#mobile-menu.absolute.top-0.leaving-0.w-full.hidden.z-10
|
||||
.p-5.bg-white.border.rounded.shadow-sm
|
||||
.flex.items-center.justify-between.mb-4
|
||||
%div
|
||||
%a.inline-flex.items-center{"aria-label" => "Hub Feenix", :href => "/", :title => "Hub Feenix"}
|
||||
= image_tag("feenix_lintu.webp" , class: "h-20")
|
||||
%span.ml-2.text-xl.font-bold.tracking-wide.text-gray-800.uppercase Hub Feenix
|
||||
%div
|
||||
%button.p-2.-mt-2.-mr-2.transition.duration-200.rounded.hover:bg-gray-200.focus:bg-gray-200.focus:outline-none.focus:shadow-outline{"aria-label" => "Close Menu", :title => "Close Menu" , onclick: "menu_off();"}
|
||||
%svg.w-5.text-gray-600{:viewbox => "0 0 24 24"}
|
||||
%path{:d => "M19.7,4.3c-0.4-0.4-1-0.4-1.4,0L12,10.6L5.7,4.3c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l6.3,6.3l-6.3,6.3 c-0.4,0.4-0.4,1,0,1.4C4.5,19.9,4.7,20,5,20s0.5-0.1,0.7-0.3l6.3-6.3l6.3,6.3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3 c0.4-0.4,0.4-1,0-1.4L13.4,12l6.3-6.3C20.1,5.3,20.1,4.7,19.7,4.3z", :fill => "currentColor"}
|
||||
%nav
|
||||
%ul.space-y-6.px-20.w-lg.text-center
|
||||
- main_menu.each do |link , text|
|
||||
%li
|
||||
%a.w-full.h-full.block.tracking-wide.text-xl.p-2.rounded-lg.hover:bg-cyan-200{ :href => link , :title => text}
|
||||
= text
|
||||
%li
|
||||
%hr
|
||||
- mobile_menu.each do |link , text|
|
||||
%li
|
||||
%a.w-full.h-full.block.tracking-wide.text-xl.p-2.rounded-lg.hover:bg-cyan-200{ :href => link , :title => text}
|
||||
= text
|
||||
-if(current_member)
|
||||
= form_tag( main_app.destroy_member_session_path , {method: :delete ,class: "text-center"}) do
|
||||
%button.w-full.items-center.gap-2.rounded-lg.px-4.py-2.text-sm.text-blue-700.hover:bg-red-50{:role => "menuitem", :type => "submit"}
|
||||
%svg.h-4.w-4{:fill => "none", :stroke => "currentColor", "stroke-width" => "2", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
||||
%path{:d => "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
|
||||
Sign out
|
||||
-else
|
||||
%a.inline-flex.items-center.justify-center.h-12.px-6.font-medium.tracking-wide.text-white.transition.duration-200.rounded-lg.shadow-md.bg-green-800.hover:bg-blue-800.focus:shadow-outline.focus:outline-none{"aria-label" => "Sign up", :href => main_app.member_session_path, :title => "Log in or Sign up"}
|
||||
Login
|
||||
:javascript
|
||||
var drop_hidden = true;
|
||||
function menu_on() {
|
||||
var x = document.getElementById("mobile-menu");
|
||||
x.style.display = "block";
|
||||
}
|
||||
function menu_off() {
|
||||
var x = document.getElementById("mobile-menu");
|
||||
x.style.display = "none";
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
!!!
|
||||
%html
|
||||
%head
|
||||
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
|
||||
%title Hubfeenix Makerspace
|
||||
%meta{:content => "width=device-width,initial-scale=1", :name => "viewport"}/
|
||||
// https://www.favicon-generator.org/
|
||||
%link{:href => "/apple-icon-57x57.png", :rel => "apple-touch-icon", :sizes => "57x57"}/
|
||||
%link{:href => "/apple-icon-60x60.png", :rel => "apple-touch-icon", :sizes => "60x60"}/
|
||||
%link{:href => "/apple-icon-72x72.png", :rel => "apple-touch-icon", :sizes => "72x72"}/
|
||||
%link{:href => "/apple-icon-76x76.png", :rel => "apple-touch-icon", :sizes => "76x76"}/
|
||||
%link{:href => "/apple-icon-114x114.png", :rel => "apple-touch-icon", :sizes => "114x114"}/
|
||||
%link{:href => "/apple-icon-120x120.png", :rel => "apple-touch-icon", :sizes => "120x120"}/
|
||||
%link{:href => "/apple-icon-144x144.png", :rel => "apple-touch-icon", :sizes => "144x144"}/
|
||||
%link{:href => "/apple-icon-152x152.png", :rel => "apple-touch-icon", :sizes => "152x152"}/
|
||||
%link{:href => "/apple-icon-180x180.png", :rel => "apple-touch-icon", :sizes => "180x180"}/
|
||||
%link{:href => "/android-icon-192x192.png", :rel => "icon", :sizes => "192x192", :type => "image/png"}/
|
||||
%link{:href => "/favicon-32x32.png", :rel => "icon", :sizes => "32x32", :type => "image/png"}/
|
||||
%link{:href => "/favicon-96x96.png", :rel => "icon", :sizes => "96x96", :type => "image/png"}/
|
||||
%link{:href => "/favicon-16x16.png", :rel => "icon", :sizes => "16x16", :type => "image/png"}/
|
||||
%link{:href => "/manifest.json", :rel => "manifest"}/
|
||||
%meta{:content => "#ffffff", :name => "msapplication-TileColor"}/
|
||||
%meta{:content => "/ms-icon-144x144.png", :name => "msapplication-TileImage"}/
|
||||
%meta{:content => "#ffffff", :name => "theme-color"}/
|
||||
|
||||
= csrf_meta_tags
|
||||
= csp_meta_tag
|
||||
= stylesheet_link_tag "tailwind"
|
||||
= stylesheet_link_tag "application"
|
||||
|
||||
= javascript_importmap_tags
|
||||
- if false
|
||||
%script{:src => "https://cdn.tailwindcss.com"}
|
||||
|
||||
%body.xl:mx-auto{class: "max-w-[1920px]"}
|
||||
= render "layouts/header"
|
||||
= render "layouts/messages"
|
||||
= yield
|
||||
= render "layouts/footer"
|
|
@ -0,0 +1,8 @@
|
|||
!!!
|
||||
%html
|
||||
%head
|
||||
%meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}/
|
||||
:css
|
||||
/* Email styles need to be inline */
|
||||
%body
|
||||
= yield
|
|
@ -0,0 +1 @@
|
|||
= yield
|
|
@ -0,0 +1,23 @@
|
|||
!!!
|
||||
%html
|
||||
%head
|
||||
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
|
||||
%title
|
||||
Forum #{yield :thredded_page_title}
|
||||
%meta{:content => "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0", :name => "viewport"}/
|
||||
= stylesheet_link_tag "tailwind"
|
||||
= stylesheet_link_tag 'thredded', 'data-turbolinks-track': 'reload'
|
||||
= stylesheet_link_tag "application"
|
||||
= csrf_meta_tag
|
||||
= csp_meta_tag
|
||||
= javascript_include_tag 'thredded', |
|
||||
async: !Rails.application.config.assets.debug, |
|
||||
defer: true, |
|
||||
'data-turbolinks-track': 'reload' |
|
||||
= RailsGravatar.prefetch_dns_tag
|
||||
%meta{:content => "width=device-width, initial-scale=1, user-scalable=no", :name => "viewport"}/
|
||||
%body
|
||||
= render "layouts/header"
|
||||
= render "layouts/messages"
|
||||
= yield
|
||||
= render "layouts/footer"
|
|
@ -0,0 +1,26 @@
|
|||
%script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
|
||||
%script{:src => "https://cdn.jsdelivr.net/npm/marked/marked.min.js"}
|
||||
|
||||
.flex.justify-center.m-5.m-5.md:m-12.lg:m-20
|
||||
.flex.flex-col.text-center
|
||||
%h1.text-4xl Edit your profile
|
||||
|
||||
.flex.justify-center.m-5.m-5.md:m-12.lg:m-20
|
||||
.flex.flex-col.text-center{class: "w-full md:w-10/12"}
|
||||
The Picture box is landscape with ratio 3/4.
|
||||
= simple_form_for @member do |f|
|
||||
.grid.grid-cols-1.md:grid-cols-2.gap-10
|
||||
= render "merged/form/editor" , object: @member , field: :bio, form: f
|
||||
.info.mr-8
|
||||
.text-red-700= f.error_notification
|
||||
= f.input :name
|
||||
.flex.h-16.mt-2.col-span-2
|
||||
= image_tag(@member.picture_url , class: "align-middle mr-4") if @member.picture?
|
||||
.w-full= f.input :picture , as: :file ,
|
||||
label: (@member.picture.blank? ? "Add picture" : "Change picture")
|
||||
= f.hidden_field :picture_cache
|
||||
.flex.justify-center.actions.m-10
|
||||
= f.button :button, "Update", class: button_classes + " bg-cyan-200"
|
||||
= link_to member_path(@member) do
|
||||
%button.ml-10{type: :submit, class: button_classes}
|
||||
Back
|
|
@ -0,0 +1,20 @@
|
|||
= paginate @members
|
||||
|
||||
.flex.justify-center.m-8.mx-5.md:mx-12.lg:mx-20
|
||||
.flex.flex-col.text-center
|
||||
%h1.text-4xl Current Makerspace at Hub Feenix
|
||||
|
||||
.mx-20.grid.grid-cols-1.md:grid-cols-2.lg:grid-cols-3.2xl:grid-cols-4.gap-8.md:gap-12.lg:gap-16
|
||||
- @members.each do |member|
|
||||
.overflow-hidden.border.border-gray-100.shadow-sm
|
||||
.h-0.overflow-hidden.relative{class: "pt-[125%]"}
|
||||
=link_to member , class: "absolute h-60 top-0 left-0 w-full h-full" do
|
||||
= picture_for( member , class: "object-cover")
|
||||
%h3.pt-5.text-2xl.bg-gray-100.text-black.font-bold.text-center
|
||||
= member.name
|
||||
.p-2.text-xs.bg-gray-50.text-black.font-bold.text-center
|
||||
= member.name
|
||||
%div.h-full
|
||||
.p-5.text-center
|
||||
.m-2.text-sm.leading-relaxed.line-clamp-3{ prose_classes }
|
||||
= markdown shorten(member.bio)
|
|
@ -0,0 +1,57 @@
|
|||
.px-4.py-16.mx-auto.sm:max-w-xl.md:max-w-full.lg:max-w-screen-xl.md:px-24.lg:px-8.lg:py-20
|
||||
.flex.flex-col.max-w-screen-lg.overflow-hidden.bg-white.border.rounded.shadow-sm.lg:flex-row.sm:mx-auto
|
||||
.relative{:class => "lg:w-1/2"}
|
||||
-if @member.picture_url
|
||||
= image_tag @member.picture_url, class: "object-cover w-full lg:absolute h-80 lg:h-full"
|
||||
.flex.flex-col.justify-center.p-8.lg:p-16.lg:pl-10{:class => "lg:w-1/2"}
|
||||
%div
|
||||
%p.inline-block.px-3.py-px.mb-4.text-xs.font-semibold.tracking-wider.text-teal-900.uppercase.rounded-full.bg-teal-accent-400
|
||||
= @member.name
|
||||
%h5.mb-3.text-3xl.font-extrabold.leading-none.sm:text-4xl
|
||||
= @member.name
|
||||
.mb-8.text-gray-800
|
||||
.prose= markdown(@member.bio)
|
||||
|
||||
- if current_member == @member
|
||||
.flex.justify-around.ml-20
|
||||
= link_to edit_member_path(@member) do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Edit Profile
|
||||
|
||||
= link_to edit_member_registration_path do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Change Password
|
||||
|
||||
= link_to new_story_path() do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
New Story
|
||||
|
||||
= link_to new_picture_path() do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
New Picture
|
||||
|
||||
= form_tag( destroy_member_session_path , {method: :delete } ) do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400{type: :submit}
|
||||
Sign out
|
||||
|
||||
- @member.stories.each do |story|
|
||||
=render_story( story )
|
||||
- if current_member == @member
|
||||
.flex.justify-around
|
||||
= link_to edit_story_path(story) do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Edit Story
|
||||
|
||||
.mx-20.grid.grid-cols-1.md:grid-cols-2.lg:grid-cols-3.xl:grid-cols-4.gap-8.md:gap-12.lg:gap-16
|
||||
- @member.pictures.each do |picture|
|
||||
%div
|
||||
= render picture , picture: picture
|
||||
- if current_member == @member
|
||||
.flex.justify-around
|
||||
= link_to edit_picture_path(picture) do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Edit Picture
|
||||
:javascript
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
const lightbox = GLightbox({ });
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
.mx-20.grid.grid-cols-1.md:grid-cols-2.lg:grid-cols-3.2xl:grid-cols-4.gap-8.md:gap-12.lg:gap-16
|
||||
- Picture.all.limit(4).each do |picture|
|
||||
= render "pictures/picture" , picture: picture
|
||||
|
||||
:javascript
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
const lightbox = GLightbox({ });
|
||||
});
|
|
@ -0,0 +1,2 @@
|
|||
- story = Story.last
|
||||
= render_story story
|
|
@ -0,0 +1,18 @@
|
|||
%div
|
||||
Pictures may have a small text, that will be diplayed on top of the
|
||||
picure. The Picture box is landscape with ratio 3/4.
|
||||
= simple_form_for @picture do |f|
|
||||
= f.error_notification
|
||||
.flex.h-16.mt-2
|
||||
= image_tag(@picture.picture_url , class: "align-middle mr-2") if @picture.picture?
|
||||
.w-full= f.input :picture , as: :file ,
|
||||
label: (@picture.picture.blank? ? "Add picture" : "Change picture")
|
||||
= f.hidden_field :picture_cache
|
||||
= f.input :text , as: :text , input_html: { rows: 2 }
|
||||
= f.input :happened , wrapper_class: "flex mt-4 align-center"
|
||||
.flex.justify-between.mt-6
|
||||
%button.bg-cyan-200.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
= f.submit 'Save'
|
||||
= link_to member_path(current_member) do
|
||||
%button.ml-20.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Back
|
|
@ -0,0 +1,13 @@
|
|||
.group.relative.overflow-hidden
|
||||
.flex.justify-between
|
||||
.ml-2= link_to picture.member.name , main_app.member_path(picture.member) , class: :underline
|
||||
.mr-2
|
||||
= distance_of_time_in_words_to_now picture.happened
|
||||
ago
|
||||
.h-0.overflow-hidden.relative{class: "pt-[75%]"}
|
||||
=link_to someones_path( picture ) , {class: :glightbox ,
|
||||
"data-glightbox" => "title: #{picture.text}" } do
|
||||
= picture_for( picture , "absolute top-0 left-0 w-full h-full inset-0 object-cover hover:scale-105 ease-in duration-500")
|
||||
-unless picture.text.blank?
|
||||
.absolute.bottom-0.leaving-0.right-0.px-4.pb-1.bg-gray-800.opacity-70.transition-colors.group-hover:bg-black.group-hover:opacity-100
|
||||
.text-center.mt-2.text-white= picture.text
|
|
@ -0,0 +1,7 @@
|
|||
%script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
|
||||
%script{:src => "https://cdn.jsdelivr.net/npm/marked/marked.min.js"}
|
||||
.flex.justify-center
|
||||
.column{class: "w-10/12 md:w-8/12 lg:w-7/12 xl:w-6/12"}
|
||||
.text-2xl.font-bold.my-4
|
||||
Edit Picture
|
||||
= render 'form'
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
= paginate @pictures
|
||||
|
||||
.flex.justify-end.mr-10
|
||||
= sort_link(@q, :happened ,class: 'flex flex-nowrap text-md')
|
||||
.border-r-4.mx-4
|
||||
= sort_link(@q, :created_at , class: 'flex flex-nowrap text-md')
|
||||
|
||||
.mx-20.grid.grid-cols-1.md:grid-cols-2.lg:grid-cols-3.2xl:grid-cols-4.gap-8.md:gap-12.lg:gap-16
|
||||
- @pictures.each do |picture|
|
||||
= render picture , picture: picture
|
||||
|
||||
.flex.ml-20
|
||||
= link_to new_picture_path do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
New Picture
|
||||
|
||||
:javascript
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
const lightbox = GLightbox({ });
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
%script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
|
||||
%script{:src => "https://cdn.jsdelivr.net/npm/marked/marked.min.js"}
|
||||
.flex.justify-center
|
||||
.column{class: "w-10/12 md:w-8/12 lg:w-7/12 xl:w-6/12"}
|
||||
.text-2xl.font-bold.my-4
|
||||
New Picture
|
||||
= render 'form'
|
|
@ -0,0 +1,11 @@
|
|||
.grid.grid-cols-1.md:grid-cols-2.lg:grid-cols-3.gap-8.md:gap-12.lg:gap-16
|
||||
%div
|
||||
= render @picture , picture: @picture
|
||||
|
||||
.mx-20.flex.justify-between
|
||||
= link_to edit_picture_path(@picture) do
|
||||
%button.mt-6.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Edit
|
||||
= link_to pictures_path do
|
||||
%button.mt-6.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Back
|
|
@ -0,0 +1,20 @@
|
|||
%div
|
||||
Story layout changes with the amount of text.
|
||||
For short text a wide picture is best. Otherwise square, and for
|
||||
longer text a high picture also works.
|
||||
= simple_form_for @story do |f|
|
||||
= f.error_notification
|
||||
.flex.h-16.mt-2
|
||||
= image_tag(@story.picture_url , class: "align-middle mr-2") if @story.picture?
|
||||
.w-full= f.input :picture , as: :file ,
|
||||
label: (@story.picture.blank? ? "Add picture" : "Change picture")
|
||||
= f.hidden_field :picture_cache
|
||||
= f.input :header
|
||||
= render "merged/form/editor" , object: @story , field: :text, form: f
|
||||
= f.input :happened , wrapper_class: "flex mt-4 align-center"
|
||||
.flex.justify-between.mt-6
|
||||
%button.bg-cyan-200.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
= f.submit 'Save'
|
||||
= link_to member_path(current_member) do
|
||||
%button.ml-20.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Back
|
|
@ -0,0 +1,13 @@
|
|||
%section.overflow-hidden.grid.grid-cols-1.m-5.md:m-12.lg:m-20.md:grid-cols-2
|
||||
=link_to someones_path( story ) , {class: :glightbox } do
|
||||
= picture_for( story , "h-56 w-full object-cover sm:h-full")
|
||||
.p-8.md:p-12.lg:px-16.lg:py-24
|
||||
.mx-auto.max-w-xl.text-center
|
||||
%h2.text-2xl.font-bold.md:text-4xl
|
||||
= story.header
|
||||
%h4.text-xl.mt-10.md:text-2xl
|
||||
= distance_of_time_in_words_to_now story.happened
|
||||
ago, by
|
||||
= link_to story.member.name , main_app.member_path(story.member) , class: :underline
|
||||
.mt-8{ prose_classes }
|
||||
= markdown(story.text)
|
|
@ -0,0 +1,15 @@
|
|||
%section.flex.justify-center.p-8.flex-col.md:flex-row.m-20
|
||||
.flex.items-center.h-40.md:h-60.lg:h-96.w-full.overflow-hidden{class: "lg:w-2/3"}
|
||||
=link_to someones_path( story ) , {class: :glightbox } do
|
||||
= picture_for(story ,"object-cover")
|
||||
.flex.items-center.w-full.max-w.px-6.mt-6.mx-auto{:class => "lg:w-1/3"}
|
||||
.flex-1
|
||||
.text-center
|
||||
%h2.text-4xl.font-bold.text-center.mb-4.lg:mb-8
|
||||
= story.header
|
||||
%h4.text-xl.mt-4.lg:mt-8.md:text-2xl
|
||||
= distance_of_time_in_words_to_now story.happened
|
||||
ago, by
|
||||
= link_to story.member.name , main_app.member_path(story.member) , class: :underline
|
||||
.mt-3{ prose_classes }
|
||||
= markdown(story.text)
|
|
@ -0,0 +1,13 @@
|
|||
%section.p-20.my-20
|
||||
.flex.justify-center
|
||||
.max-w-prose.text-center
|
||||
%h1.mb-10.text-2xl.font-bold.tracking-tight.sm:text-4xl
|
||||
= story.header
|
||||
.text-xl.pb-6{ prose_classes }
|
||||
= distance_of_time_in_words_to_now story.happened
|
||||
ago, by
|
||||
= link_to story.member.name , main_app.member_path(story.member) , class: :underline
|
||||
.max-w-full.mt-4.gap-16.columns-1.md:columns-2.lg:columns-3.xl:columns-4{ prose_classes }
|
||||
=link_to someones_path( story ) , {class: :glightbox } do
|
||||
= picture_for( story , "h-56 w-full object-cover sm:h-full")
|
||||
= markdown(story.text)
|
|
@ -0,0 +1,7 @@
|
|||
%script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
|
||||
%script{:src => "https://cdn.jsdelivr.net/npm/marked/marked.min.js"}
|
||||
.flex.justify-center
|
||||
.column{class: "w-10/12 md:w-8/12 lg:w-7/12 xl:w-6/12"}
|
||||
.text-2xl.font-bold.my-4
|
||||
Edit Story
|
||||
= render 'form'
|
|
@ -0,0 +1,21 @@
|
|||
= paginate @stories
|
||||
|
||||
.flex.justify-end.mr-10
|
||||
= sort_link(@q, :happened ,class: 'flex flex-nowrap text-md')
|
||||
.border-r-4.mx-4
|
||||
= sort_link(@q, :created_at , class: 'flex flex-nowrap text-md')
|
||||
|
||||
- @stories.each do |story|
|
||||
= render_story(story)
|
||||
|
||||
%br
|
||||
|
||||
.flex.ml-20
|
||||
= link_to new_story_path do
|
||||
%button.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
New Story
|
||||
|
||||
:javascript
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
const lightbox = GLightbox({ });
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
%script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
|
||||
%script{:src => "https://cdn.jsdelivr.net/npm/marked/marked.min.js"}
|
||||
.flex.justify-center
|
||||
.column{class: "w-10/12 md:w-8/12 lg:w-7/12 xl:w-6/12"}
|
||||
.text-2xl.font-bold.my-4
|
||||
New Story
|
||||
= render 'form'
|
|
@ -0,0 +1,9 @@
|
|||
= render_story @story
|
||||
|
||||
.mx-20.flex.justify-between
|
||||
= link_to edit_story_path(@story) do
|
||||
%button.mt-6.bg-cyan-200.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Edit
|
||||
= link_to stories_path do
|
||||
%button.mt-6.mr-3.inline-block.rounded-lg.px-4.py-3.text-md.font-medium.border.border-gray-400
|
||||
Back
|
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'bundle' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require "rubygems"
|
||||
|
||||
m = Module.new do
|
||||
module_function
|
||||
|
||||
def invoked_as_script?
|
||||
File.expand_path($0) == File.expand_path(__FILE__)
|
||||
end
|
||||
|
||||
def env_var_version
|
||||
ENV["BUNDLER_VERSION"]
|
||||
end
|
||||
|
||||
def cli_arg_version
|
||||
return unless invoked_as_script? # don't want to hijack other binstubs
|
||||
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
||||
bundler_version = nil
|
||||
update_index = nil
|
||||
ARGV.each_with_index do |a, i|
|
||||
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
||||
bundler_version = a
|
||||
end
|
||||
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
||||
bundler_version = $1
|
||||
update_index = i
|
||||
end
|
||||
bundler_version
|
||||
end
|
||||
|
||||
def gemfile
|
||||
gemfile = ENV["BUNDLE_GEMFILE"]
|
||||
return gemfile if gemfile && !gemfile.empty?
|
||||
|
||||
File.expand_path("../../Gemfile", __FILE__)
|
||||
end
|
||||
|
||||
def lockfile
|
||||
lockfile =
|
||||
case File.basename(gemfile)
|
||||
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
||||
else "#{gemfile}.lock"
|
||||
end
|
||||
File.expand_path(lockfile)
|
||||
end
|
||||
|
||||
def lockfile_version
|
||||
return unless File.file?(lockfile)
|
||||
lockfile_contents = File.read(lockfile)
|
||||
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
||||
Regexp.last_match(1)
|
||||
end
|
||||
|
||||
def bundler_requirement
|
||||
@bundler_requirement ||=
|
||||
env_var_version || cli_arg_version ||
|
||||
bundler_requirement_for(lockfile_version)
|
||||
end
|
||||
|
||||
def bundler_requirement_for(version)
|
||||
return "#{Gem::Requirement.default}.a" unless version
|
||||
|
||||
bundler_gem_version = Gem::Version.new(version)
|
||||
|
||||
requirement = bundler_gem_version.approximate_recommendation
|
||||
|
||||
return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
|
||||
|
||||
requirement += ".a" if bundler_gem_version.prerelease?
|
||||
|
||||
requirement
|
||||
end
|
||||
|
||||
def load_bundler!
|
||||
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
||||
|
||||
activate_bundler
|
||||
end
|
||||
|
||||
def activate_bundler
|
||||
gem_error = activation_error_handling do
|
||||
gem "bundler", bundler_requirement
|
||||
end
|
||||
return if gem_error.nil?
|
||||
require_error = activation_error_handling do
|
||||
require "bundler/version"
|
||||
end
|
||||
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
||||
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
||||
exit 42
|
||||
end
|
||||
|
||||
def activation_error_handling
|
||||
yield
|
||||
nil
|
||||
rescue StandardError, LoadError => e
|
||||
e
|
||||
end
|
||||
end
|
||||
|
||||
m.load_bundler!
|
||||
|
||||
if m.invoked_as_script?
|
||||
load Gem.bin_path("bundler", "bundle")
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
if ! gem list foreman -i --silent; then
|
||||
echo "Installing foreman..."
|
||||
gem install foreman
|
||||
fi
|
||||
|
||||
exec foreman start -f Procfile.dev "$@"
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require_relative "../config/application"
|
||||
require "importmap/commands"
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
APP_PATH = File.expand_path("../config/application", __dir__)
|
||||
require_relative "../config/boot"
|
||||
require "rails/commands"
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
require_relative "../config/boot"
|
||||
require "rake"
|
||||
Rake.application.run
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env ruby
|
||||
require "fileutils"
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = File.expand_path("..", __dir__)
|
||||
|
||||
def system!(*args)
|
||||
system(*args) || abort("\n== Command #{args} failed ==")
|
||||
end
|
||||
|
||||
FileUtils.chdir APP_ROOT do
|
||||
# This script is a way to set up or update your development environment automatically.
|
||||
# This script is idempotent, so that you can run it at any time and get an expectable outcome.
|
||||
# Add necessary setup steps to this file.
|
||||
|
||||
puts "== Installing dependencies =="
|
||||
system! "gem install bundler --conservative"
|
||||
system("bundle check") || system!("bundle install")
|
||||
|
||||
# puts "\n== Copying sample files =="
|
||||
# unless File.exist?("config/database.yml")
|
||||
# FileUtils.cp "config/database.yml.sample", "config/database.yml"
|
||||
# end
|
||||
|
||||
puts "\n== Preparing database =="
|
||||
system! "bin/rails db:prepare"
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system! "bin/rails log:clear tmp:clear"
|
||||
|
||||
puts "\n== Restarting application server =="
|
||||
system! "bin/rails restart"
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
# This file is used by Rack-based servers to start the application.
|
||||
|
||||
require_relative "config/environment"
|
||||
|
||||
run Rails.application
|
||||
Rails.application.load_server
|
|
@ -0,0 +1,45 @@
|
|||
require_relative "boot"
|
||||
|
||||
require "rails"
|
||||
# Pick the frameworks you want:
|
||||
require "active_model/railtie"
|
||||
require "active_job/railtie"
|
||||
require "active_record/railtie"
|
||||
require "action_controller/railtie"
|
||||
require "action_mailer/railtie"
|
||||
#require "active_storage/engine"
|
||||
# require "action_mailbox/engine"
|
||||
#require "action_text/engine"
|
||||
require "action_view/railtie"
|
||||
# require "action_cable/engine"
|
||||
require "rails/test_unit/railtie"
|
||||
|
||||
# Require the gems listed in Gemfile, including any gems
|
||||
# you've limited to :test, :development, or :production.
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
module Makerspace
|
||||
class Application < Rails::Application
|
||||
# Initialize configuration defaults for originally generated Rails version.
|
||||
config.load_defaults 7.0
|
||||
|
||||
config.hosts << "green-machine.local" #our "staging"
|
||||
config.hosts << "makerspace.hubfeenix.fi" #production
|
||||
config.hosts << "makerspace.staging.hubfeenix.fi"
|
||||
|
||||
config.active_job.queue_adapter = :sucker_punch
|
||||
|
||||
# Configuration for the application, engines, and railties goes here.
|
||||
#
|
||||
# These settings can be overridden in specific environments using the files
|
||||
# in config/environments, which are processed later.
|
||||
#
|
||||
# config.time_zone = "Central Time (US & Canada)"
|
||||
# config.eager_load_paths << Rails.root.join("extras")
|
||||
|
||||
#config.autoload_paths << Rails.root.join('lib')
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
ActionView::Base.default_form_builder = SimpleForm::Tailwind::FormBuilder
|
|
@ -0,0 +1,4 @@
|
|||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
||||
|
||||
require "bundler/setup" # Set up gems listed in the Gemfile.
|
||||
require "bootsnap/setup" # Speed up boot time by caching expensive operations.
|
|
@ -0,0 +1 @@
|
|||
Q19CEUFE4CUDnPMXGnDXjuyEpTIlxfSeHDcLgkIAs7iKb8ROgOFWfhS10A+l2xuqYVe6Os+rbysTRi5mgns+ctwYYTS1uek6a8vXss5N0XcOJdCnp5vynvcNtB/5n2qwkUaZY6vMD10Wpgvtxn43M9ntWEshj2Z/UCraa35aGuw1vYq4sA7TZ0C1SCnK6uBjYHFhUl8j7Qq17qN3Zs8FW63MuwHPzodLYHfjgwVsRaxvNqEDdTWbeBS50XB4wSwkgp5prhw0/f2/hp3a4EyhiFGTqr0zMIv5ejHgNxc+6am72j4XylyJhmnf3XzM/ClS+Ue00sAOKOgIkdqbvLiRepCooi9+tpJpzXSPwVrRbM/SUM/n8XuELr9KX8EBh2xkYlIW+/zgQsGmR0eZSx6z2CsFfrxu5l9MVJf7H68ktr2SphoeWbB2yx0cE0vGz1p2/bKFdhGNEMvTbSzsrbJos0mSoQiNg7dgEkbOb/J7DJRXdWMRk7+6cZTlWgOCcg==--Vc0Hz1o+k6DP9og1--cY0qLkrOq7V2YfIRwjkqEQ==
|
|
@ -0,0 +1,20 @@
|
|||
default: &default
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
username: postgres
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
database: makerspace_development
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
test:
|
||||
<<: *default
|
||||
database: makerspace_test
|
||||
|
||||
#
|
||||
production:
|
||||
<<: *default
|
||||
database: makerspace_production
|
|
@ -0,0 +1,81 @@
|
|||
require 'mina/rails'
|
||||
require 'mina/git'
|
||||
require 'mina/rbenv' # for rbenv support. (https://rbenv.org)
|
||||
|
||||
# Basic settings:
|
||||
# domain - The hostname to SSH to.
|
||||
# deploy_to - Path to deploy into.
|
||||
# repository - Git repo to clone from. (needed by mina/git)
|
||||
# branch - Branch name to deploy. (needed by mina/git)
|
||||
|
||||
set :application_name, 'makerspace'
|
||||
#set :domain, 'www.rubydesign.fi'
|
||||
set :domain, '95.217.60.123'
|
||||
set :deploy_to, '/home/feenix/makerspace'
|
||||
set :repository, "https://github.com/FeenixMakers/makerspace.git"
|
||||
set :branch, 'main'
|
||||
|
||||
# Optional settings:
|
||||
set :user, 'feenix' # Username in the server to SSH to.
|
||||
# set :port, '30000' # SSH port number.
|
||||
# set :forward_agent, true # SSH forward_agent.
|
||||
|
||||
# Shared dirs and files will be symlinked into the app-folder by the 'deploy:link_shared_paths' step.
|
||||
# Some plugins already add folders to shared_dirs like `mina/rails` add `public/assets`, `vendor/bundle` and many more
|
||||
# run `mina -d` to see all folders and files already included in `shared_dirs` and `shared_files`
|
||||
set :shared_dirs, fetch(:shared_dirs, []).push('tmp/pids' , 'tmp/sockets' , 'public/uploads')
|
||||
set :shared_files, fetch(:shared_files, []).push('config/master.key')
|
||||
|
||||
set :force_migrate , true
|
||||
|
||||
# This task is the environment that is loaded for all remote run commands, such as
|
||||
# `mina deploy` or `mina rake`.
|
||||
task :remote_environment do
|
||||
# If you're using rbenv, use this to load the rbenv environment.
|
||||
# Be sure to commit your .ruby-version or .rbenv-version to your repository.
|
||||
invoke :'rbenv:load'
|
||||
|
||||
end
|
||||
|
||||
# Put any custom commands you need to run at setup
|
||||
# All paths in `shared_dirs` and `shared_paths` will be created on their own.
|
||||
task :setup do
|
||||
# command %{rbenv install 2.5.3 --skip-existing}
|
||||
# command %{rvm install ruby-2.5.3}
|
||||
# command %{gem install bundler}
|
||||
end
|
||||
|
||||
desc "Deploys the current version to the server."
|
||||
task :deploy do
|
||||
# uncomment this line to make sure you pushed your local branch to the remote origin
|
||||
# invoke :'git:ensure_pushed'
|
||||
deploy do
|
||||
# Put things that will set up an empty directory into a fully set-up
|
||||
# instance of your project.
|
||||
invoke :'git:clone'
|
||||
invoke :'deploy:link_shared_paths'
|
||||
invoke :'bundle:install'
|
||||
invoke :'rails:assets_precompile'
|
||||
invoke :'rails:db_migrate'
|
||||
invoke :'deploy:cleanup'
|
||||
|
||||
on :launch do
|
||||
in_path(fetch(:current_path)) do
|
||||
invoke :'passenger:restart'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# you can use `run :local` to run tasks on local machine before of after the deploy scripts
|
||||
# run(:local){ say 'done' }
|
||||
end
|
||||
|
||||
namespace :passenger do
|
||||
desc "Restart Passenger"
|
||||
task :restart do
|
||||
command %{
|
||||
echo "-----> Restarting passenger"
|
||||
#{echo_cmd %[touch tmp/restart.txt]}
|
||||
}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
# Load the Rails application.
|
||||
require_relative "application"
|
||||
|
||||
# Initialize the Rails application.
|
||||
Rails.application.initialize!
|
|
@ -0,0 +1,75 @@
|
|||
require "active_support/core_ext/integer/time"
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# In the development environment your application's code is reloaded any time
|
||||
# it changes. This slows down response time but is perfect for development
|
||||
# since you don't have to restart the web server when you make code changes.
|
||||
config.cache_classes = false
|
||||
|
||||
# Do not eager load code on boot.
|
||||
config.eager_load = false
|
||||
|
||||
# Show full error reports.
|
||||
config.consider_all_requests_local = true
|
||||
|
||||
# Enable server timing
|
||||
config.server_timing = true
|
||||
|
||||
# Enable/disable caching. By default caching is disabled.
|
||||
# Run rails dev:cache to toggle caching.
|
||||
if Rails.root.join("tmp/caching-dev.txt").exist?
|
||||
config.action_controller.perform_caching = true
|
||||
config.action_controller.enable_fragment_cache_logging = true
|
||||
|
||||
config.cache_store = :memory_store
|
||||
config.public_file_server.headers = {
|
||||
"Cache-Control" => "public, max-age=#{2.days.to_i}"
|
||||
}
|
||||
else
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
config.cache_store = :null_store
|
||||
end
|
||||
|
||||
|
||||
config.public_file_server.enabled = true
|
||||
|
||||
# Don't care if the mailer can't send.
|
||||
config.action_mailer.raise_delivery_errors = false
|
||||
config.action_mailer.perform_caching = false
|
||||
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
||||
|
||||
routes.default_url_options = { host: 'localhost', port: 3000 }
|
||||
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
# Raise exceptions for disallowed deprecations.
|
||||
config.active_support.disallowed_deprecation = :raise
|
||||
|
||||
# Tell Active Support which deprecation messages to disallow.
|
||||
config.active_support.disallowed_deprecation_warnings = []
|
||||
|
||||
# Raise an error on page load if there are pending migrations.
|
||||
config.active_record.migration_error = :page_load
|
||||
|
||||
# Highlight code that triggered database queries in logs.
|
||||
config.active_record.verbose_query_logs = true
|
||||
|
||||
# Suppress logger output for asset requests.
|
||||
config.assets.quiet = false
|
||||
config.assets.debug = true
|
||||
config.assets.unknown_asset_fallback = false
|
||||
|
||||
# Raises error for missing translations.
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
# Annotate rendered view with file names.
|
||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||
|
||||
# Uncomment if you wish to allow Action Cable access from any origin.
|
||||
# config.action_cable.disable_request_forgery_protection = true
|
||||
end
|
|
@ -0,0 +1,105 @@
|
|||
require "active_support/core_ext/integer/time"
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Code is not reloaded between requests.
|
||||
config.cache_classes = true
|
||||
|
||||
# Eager load code on boot. This eager loads most of Rails and
|
||||
# your application in memory, allowing both threaded web servers
|
||||
# and those relying on copy on write to perform better.
|
||||
# Rake tasks automatically ignore this option for performance.
|
||||
config.eager_load = true
|
||||
|
||||
# Full error reports are disabled and caching is turned on.
|
||||
config.consider_all_requests_local = false
|
||||
config.action_controller.perform_caching = true
|
||||
|
||||
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
|
||||
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
|
||||
# config.require_master_key = true
|
||||
|
||||
# Disable serving static files from the `/public` folder by default since
|
||||
# Apache or NGINX already handles this.
|
||||
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
|
||||
|
||||
# Compress CSS using a preprocessor.
|
||||
config.assets.css_compressor = nil
|
||||
|
||||
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
||||
config.assets.compile = false
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
||||
# config.asset_host = "http://assets.example.com"
|
||||
|
||||
# Specifies the header that your server uses for sending files.
|
||||
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
|
||||
# config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
|
||||
|
||||
|
||||
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||
# config.force_ssl = true
|
||||
|
||||
# Include generic and useful information about system operation, but avoid logging too much
|
||||
# information to avoid inadvertent exposure of personally identifiable information (PII).
|
||||
config.log_level = :info
|
||||
|
||||
# Prepend all log lines with the following tags.
|
||||
config.log_tags = [ :request_id ]
|
||||
|
||||
# Use a different cache store in production.
|
||||
# config.cache_store = :mem_cache_store
|
||||
|
||||
# Use a real queuing backend for Active Job (and separate queues per environment).
|
||||
# config.active_job.queue_adapter = :resque
|
||||
# config.active_job.queue_name_prefix = "hubfeenix_fi_production"
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Ignore bad email addresses and do not raise email delivery errors.
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
|
||||
config.action_mailer.smtp_settings = {
|
||||
:address => Rails.application.credentials.mail_server,
|
||||
:port => 465,
|
||||
:domain => Rails.application.credentials.domain_name,
|
||||
:user_name => Rails.application.credentials.admin_email,
|
||||
:password => Rails.application.credentials.admin_pass,
|
||||
:ssl => true,
|
||||
:tls => true,
|
||||
:authentication => :login,
|
||||
:enable_starttls_auto => true
|
||||
}
|
||||
|
||||
# ActionMailer Config
|
||||
config.action_mailer.default_url_options = { :host => Rails.application.credentials.domain_name }
|
||||
config.action_mailer.delivery_method = :smtp
|
||||
config.action_mailer.perform_deliveries = true
|
||||
config.action_mailer.raise_delivery_errors = true
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Don't log any deprecations.
|
||||
config.active_support.report_deprecations = false
|
||||
|
||||
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||
config.log_formatter = ::Logger::Formatter.new
|
||||
|
||||
# Use a different logger for distributed setups.
|
||||
# require "syslog/logger"
|
||||
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
|
||||
|
||||
if ENV["RAILS_LOG_TO_STDOUT"].present?
|
||||
logger = ActiveSupport::Logger.new(STDOUT)
|
||||
logger.formatter = config.log_formatter
|
||||
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
||||
end
|
||||
|
||||
# Do not dump schema after migrations.
|
||||
config.active_record.dump_schema_after_migration = false
|
||||
end
|
|
@ -0,0 +1,58 @@
|
|||
require "active_support/core_ext/integer/time"
|
||||
|
||||
# The test environment is used exclusively to run your application's
|
||||
# test suite. You never need to work with it otherwise. Remember that
|
||||
# your test database is "scratch space" for the test suite and is wiped
|
||||
# and recreated between test runs. Don't rely on the data there!
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Turn false under Spring and add config.action_view.cache_template_loading = true.
|
||||
config.cache_classes = true
|
||||
|
||||
# Eager loading loads your whole application. When running a single test locally,
|
||||
# this probably isn't necessary. It's a good idea to do in a continuous integration
|
||||
# system, or in some way before deploying your code.
|
||||
config.eager_load = ENV["CI"].present?
|
||||
|
||||
# Configure public file server for tests with Cache-Control for performance.
|
||||
config.public_file_server.enabled = true
|
||||
config.public_file_server.headers = {
|
||||
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
|
||||
}
|
||||
|
||||
# Show full error reports and disable caching.
|
||||
config.consider_all_requests_local = true
|
||||
config.action_controller.perform_caching = false
|
||||
config.cache_store = :null_store
|
||||
|
||||
# Raise exceptions instead of rendering exception templates.
|
||||
config.action_dispatch.show_exceptions = false
|
||||
|
||||
# Disable request forgery protection in test environment.
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Tell Action Mailer not to deliver emails to the real world.
|
||||
# The :test delivery method accumulates sent emails in the
|
||||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
# Raise exceptions for disallowed deprecations.
|
||||
config.active_support.disallowed_deprecation = :raise
|
||||
|
||||
# Tell Active Support which deprecation messages to disallow.
|
||||
config.active_support.disallowed_deprecation_warnings = []
|
||||
|
||||
# Raises error for missing translations.
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
# Annotate rendered view with file names.
|
||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
# Pin npm packages by running ./bin/importmap
|
||||
|
||||
pin "application", preload: true
|
||||
pin "glightbox", to: "https://ga.jspm.io/npm:glightbox@3.2.0/dist/js/glightbox.min.js"
|
|
@ -0,0 +1,12 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets.
|
||||
Rails.application.config.assets.version = "1.0"
|
||||
|
||||
# Add additional assets to the asset load path.
|
||||
# Rails.application.config.assets.paths << Emoji.images_path
|
||||
|
||||
# Precompile additional assets.
|
||||
# application.js, application.css, and all non-JS/CSS in the app/assets
|
||||
# folder are already added.
|
||||
Rails.application.config.assets.precompile += %w( )
|
|
@ -0,0 +1,25 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Define an application-wide content security policy.
|
||||
# See the Securing Rails Applications Guide for more information:
|
||||
# https://guides.rubyonrails.org/security.html#content-security-policy-header
|
||||
|
||||
# Rails.application.configure do
|
||||
# config.content_security_policy do |policy|
|
||||
# policy.default_src :self, :https
|
||||
# policy.font_src :self, :https, :data
|
||||
# policy.img_src :self, :https, :data
|
||||
# policy.object_src :none
|
||||
# policy.script_src :self, :https
|
||||
# policy.style_src :self, :https
|
||||
# # Specify URI for violation reports
|
||||
# # policy.report_uri "/csp-violation-report-endpoint"
|
||||
# end
|
||||
#
|
||||
# # Generate session nonces for permitted importmap and inline scripts
|
||||
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
|
||||
# config.content_security_policy_nonce_directives = %w(script-src)
|
||||
#
|
||||
# # Report violations without enforcing the policy.
|
||||
# # config.content_security_policy_report_only = true
|
||||
# end
|
|
@ -0,0 +1,314 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Assuming you have not yet modified this file, each configuration option below
|
||||
# is set to its default value. Note that some are commented out while others
|
||||
# are not: uncommented lines are intended to protect your configuration from
|
||||
# breaking changes in upgrades (i.e., in the event that future versions of
|
||||
# Devise change the default values for those options).
|
||||
#
|
||||
# Use this hook to configure devise mailer, warden hooks and so forth.
|
||||
# Many of these configuration options can be set straight in your model.
|
||||
Devise.setup do |config|
|
||||
# The secret key used by Devise. Devise uses this key to generate
|
||||
# random tokens. Changing this key will render invalid all existing
|
||||
# confirmation, reset password and unlock tokens in the database.
|
||||
# Devise will use the `secret_key_base` as its `secret_key`
|
||||
# by default. You can change it below and use your own secret key.
|
||||
# config.secret_key = '4f9bf8cbc1e7223b8753aaba3990d72a4a241eaa4f7490e12f98491022effe8e15b1ac284d01c1c440636d414507fb60170bbb64955f2dbec2a6557cb9a1dfc0'
|
||||
|
||||
# ==> Controller configuration
|
||||
# Configure the parent class to the devise controllers.
|
||||
# config.parent_controller = 'DeviseController'
|
||||
|
||||
# ==> Mailer Configuration
|
||||
# Configure the e-mail address which will be shown in Devise::Mailer,
|
||||
# note that it will be overwritten if you use your own mailer class
|
||||
# with default "from" parameter.
|
||||
config.mailer_sender = 'makerspace@hubfeenix.fi'
|
||||
|
||||
# Configure the class responsible to send e-mails.
|
||||
# config.mailer = 'Devise::Mailer'
|
||||
|
||||
# Configure the parent class responsible to send e-mails.
|
||||
# config.parent_mailer = 'ActionMailer::Base'
|
||||
|
||||
# ==> ORM configuration
|
||||
# Load and configure the ORM. Supports :active_record (default) and
|
||||
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
||||
# available as additional gems.
|
||||
require 'devise/orm/active_record'
|
||||
|
||||
# ==> Configuration for any authentication mechanism
|
||||
# Configure which keys are used when authenticating a user. The default is
|
||||
# just :email. You can configure it to use [:username, :subdomain], so for
|
||||
# authenticating a user, both parameters are required. Remember that those
|
||||
# parameters are used only when authenticating and not when retrieving from
|
||||
# session. If you need permissions, you should implement that in a before filter.
|
||||
# You can also supply a hash where the value is a boolean determining whether
|
||||
# or not authentication should be aborted when the value is not present.
|
||||
# config.authentication_keys = [:email]
|
||||
|
||||
# Configure parameters from the request object used for authentication. Each entry
|
||||
# given should be a request method and it will automatically be passed to the
|
||||
# find_for_authentication method and considered in your model lookup. For instance,
|
||||
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
|
||||
# The same considerations mentioned for authentication_keys also apply to request_keys.
|
||||
# config.request_keys = []
|
||||
|
||||
# Configure which authentication keys should be case-insensitive.
|
||||
# These keys will be downcased upon creating or modifying a user and when used
|
||||
# to authenticate or find a user. Default is :email.
|
||||
config.case_insensitive_keys = [:email]
|
||||
|
||||
# Configure which authentication keys should have whitespace stripped.
|
||||
# These keys will have whitespace before and after removed upon creating or
|
||||
# modifying a user and when used to authenticate or find a user. Default is :email.
|
||||
config.strip_whitespace_keys = [:email]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# It can be set to an array that will enable params authentication only for the
|
||||
# given strategies, for example, `config.params_authenticatable = [:database]` will
|
||||
# enable it only for database (email + password) authentication.
|
||||
# config.params_authenticatable = true
|
||||
|
||||
# Tell if authentication through HTTP Auth is enabled. False by default.
|
||||
# It can be set to an array that will enable http authentication only for the
|
||||
# given strategies, for example, `config.http_authenticatable = [:database]` will
|
||||
# enable it only for database authentication.
|
||||
# For API-only applications to support authentication "out-of-the-box", you will likely want to
|
||||
# enable this with :database unless you are using a custom strategy.
|
||||
# The supported strategies are:
|
||||
# :database = Support basic authentication with authentication key + password
|
||||
# config.http_authenticatable = false
|
||||
|
||||
# If 401 status code should be returned for AJAX requests. True by default.
|
||||
# config.http_authenticatable_on_xhr = true
|
||||
|
||||
# The realm used in Http Basic Authentication. 'Application' by default.
|
||||
# config.http_authentication_realm = 'Application'
|
||||
|
||||
# It will change confirmation, password recovery and other workflows
|
||||
# to behave the same regardless if the e-mail provided was right or wrong.
|
||||
# Does not affect registerable.
|
||||
# config.paranoid = true
|
||||
|
||||
# By default Devise will store the user in session. You can skip storage for
|
||||
# particular strategies by setting this option.
|
||||
# Notice that if you are skipping storage for all authentication paths, you
|
||||
# may want to disable generating routes to Devise's sessions controller by
|
||||
# passing skip: :sessions to `devise_for` in your config/routes.rb
|
||||
config.skip_session_storage = [:http_auth]
|
||||
|
||||
# By default, Devise cleans up the CSRF token on authentication to
|
||||
# avoid CSRF token fixation attacks. This means that, when using AJAX
|
||||
# requests for sign in and sign up, you need to get a new CSRF token
|
||||
# from the server. You can disable this option at your own risk.
|
||||
# config.clean_up_csrf_token_on_authentication = true
|
||||
|
||||
# When false, Devise will not attempt to reload routes on eager load.
|
||||
# This can reduce the time taken to boot the app but if your application
|
||||
# requires the Devise mappings to be loaded during boot time the application
|
||||
# won't boot properly.
|
||||
# config.reload_routes = true
|
||||
|
||||
# ==> Configuration for :database_authenticatable
|
||||
# For bcrypt, this is the cost for hashing the password and defaults to 12. If
|
||||
# using other algorithms, it sets how many times you want the password to be hashed.
|
||||
# The number of stretches used for generating the hashed password are stored
|
||||
# with the hashed password. This allows you to change the stretches without
|
||||
# invalidating existing passwords.
|
||||
#
|
||||
# Limiting the stretches to just one in testing will increase the performance of
|
||||
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
|
||||
# a value less than 10 in other environments. Note that, for bcrypt (the default
|
||||
# algorithm), the cost increases exponentially with the number of stretches (e.g.
|
||||
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
|
||||
config.stretches = Rails.env.test? ? 1 : 12
|
||||
|
||||
# Set up a pepper to generate the hashed password.
|
||||
# config.pepper = '63a04ef1757b1ac38762d301c8acafece05eddee00e63da867c01df750cc3e7cd821020ce004970ee10bb4dc276bff2f0761b4bd35e8a3c1c51cf2ad80a67d99'
|
||||
|
||||
# Send a notification to the original email when the user's email is changed.
|
||||
# config.send_email_changed_notification = false
|
||||
|
||||
# Send a notification email when the user's password is changed.
|
||||
# config.send_password_change_notification = false
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# A period that the user is allowed to access the website even without
|
||||
# confirming their account. For instance, if set to 2.days, the user will be
|
||||
# able to access the website for two days without confirming their account,
|
||||
# access will be blocked just in the third day.
|
||||
# You can also set it to nil, which will allow the user to access the website
|
||||
# without confirming their account.
|
||||
# Default is 0.days, meaning the user cannot access the website without
|
||||
# confirming their account.
|
||||
# config.allow_unconfirmed_access_for = 2.days
|
||||
|
||||
# A period that the user is allowed to confirm their account before their
|
||||
# token becomes invalid. For example, if set to 3.days, the user can confirm
|
||||
# their account within 3 days after the mail was sent, but on the fourth day
|
||||
# their account can't be confirmed with the token any more.
|
||||
# Default is nil, meaning there is no restriction on how long a user can take
|
||||
# before confirming their account.
|
||||
# config.confirm_within = 3.days
|
||||
|
||||
# If true, requires any email changes to be confirmed (exactly the same way as
|
||||
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
||||
# db field (see migrations). Until confirmed, new email is stored in
|
||||
# unconfirmed_email column, and copied to email column on successful confirmation.
|
||||
config.reconfirmable = true
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
# config.confirmation_keys = [:email]
|
||||
|
||||
# ==> Configuration for :rememberable
|
||||
# The time the user will be remembered without asking for credentials again.
|
||||
# config.remember_for = 2.weeks
|
||||
|
||||
# Invalidates all the remember me tokens when the user signs out.
|
||||
config.expire_all_remember_me_on_sign_out = true
|
||||
|
||||
# If true, extends the user's remember period when remembered via cookie.
|
||||
# config.extend_remember_period = false
|
||||
|
||||
# Options to be passed to the created cookie. For instance, you can set
|
||||
# secure: true in order to force SSL only cookies.
|
||||
# config.rememberable_options = {}
|
||||
|
||||
# ==> Configuration for :validatable
|
||||
# Range for password length.
|
||||
config.password_length = 6..40
|
||||
|
||||
# Email regex used to validate email formats. It simply asserts that
|
||||
# one (and only one) @ exists in the given string. This is mainly
|
||||
# to give user feedback and not to assert the e-mail validity.
|
||||
config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
|
||||
|
||||
# ==> Configuration for :timeoutable
|
||||
# The time you want to timeout the user session without activity. After this
|
||||
# time the user will be asked for credentials again. Default is 30 minutes.
|
||||
# config.timeout_in = 30.minutes
|
||||
|
||||
# ==> Configuration for :lockable
|
||||
# Defines which strategy will be used to lock an account.
|
||||
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
|
||||
# :none = No lock strategy. You should handle locking by yourself.
|
||||
# config.lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
# config.unlock_keys = [:email]
|
||||
|
||||
# Defines which strategy will be used to unlock an account.
|
||||
# :email = Sends an unlock link to the user email
|
||||
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
||||
# :both = Enables both strategies
|
||||
# :none = No unlock strategy. You should handle unlocking by yourself.
|
||||
# config.unlock_strategy = :both
|
||||
|
||||
# Number of authentication tries before locking an account if lock_strategy
|
||||
# is failed attempts.
|
||||
# config.maximum_attempts = 20
|
||||
|
||||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# Warn on the last attempt before the account is locked.
|
||||
# config.last_attempt_warning = true
|
||||
|
||||
# ==> Configuration for :recoverable
|
||||
#
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
# config.reset_password_keys = [:email]
|
||||
|
||||
# Time interval you can reset your password with a reset password key.
|
||||
# Don't put a too small interval or your users won't have the time to
|
||||
# change their passwords.
|
||||
config.reset_password_within = 6.hours
|
||||
|
||||
# When set to false, does not sign a user in automatically after their password is
|
||||
# reset. Defaults to true, so a user is signed in automatically after a reset.
|
||||
# config.sign_in_after_reset_password = true
|
||||
|
||||
# ==> Configuration for :encryptable
|
||||
# Allow you to use another hashing or encryption algorithm besides bcrypt (default).
|
||||
# You can use :sha1, :sha512 or algorithms from others authentication tools as
|
||||
# :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
|
||||
# for default behavior) and :restful_authentication_sha1 (then you should set
|
||||
# stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
|
||||
#
|
||||
# Require the `devise-encryptable` gem when using anything other than bcrypt
|
||||
# config.encryptor = :sha512
|
||||
|
||||
# ==> Scopes configuration
|
||||
# Turn scoped views on. Before rendering "sessions/new", it will first check for
|
||||
# "users/sessions/new". It's turned off by default because it's slower if you
|
||||
# are using only default views.
|
||||
# config.scoped_views = false
|
||||
|
||||
# Configure the default scope given to Warden. By default it's the first
|
||||
# devise role declared in your routes (usually :user).
|
||||
# config.default_scope = :user
|
||||
|
||||
# Set this configuration to false if you want /users/sign_out to sign out
|
||||
# only the current scope. By default, Devise signs out all scopes.
|
||||
# config.sign_out_all_scopes = true
|
||||
|
||||
# ==> Navigation configuration
|
||||
# Lists the formats that should be treated as navigational. Formats like
|
||||
# :html, should redirect to the sign in page when the user does not have
|
||||
# access, but formats like :xml or :json, should return 401.
|
||||
#
|
||||
# If you have any extra navigational formats, like :iphone or :mobile, you
|
||||
# should add them to the navigational formats lists.
|
||||
#
|
||||
# The "*/*" below is required to match Internet Explorer requests.
|
||||
# config.navigational_formats = ['*/*', :html]
|
||||
|
||||
# The default HTTP method used to sign out a resource. Default is :delete.
|
||||
config.sign_out_via = :delete
|
||||
|
||||
# ==> OmniAuth
|
||||
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||
# up on your models and hooks.
|
||||
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
|
||||
|
||||
# ==> Warden configuration
|
||||
# If you want to use other strategies, that are not supported by Devise, or
|
||||
# change the failure app, you can configure them inside the config.warden block.
|
||||
#
|
||||
# config.warden do |manager|
|
||||
# manager.intercept_401 = false
|
||||
# manager.default_strategies(scope: :user).unshift :some_external_strategy
|
||||
# end
|
||||
|
||||
# ==> Mountable engine configurations
|
||||
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
|
||||
# is mountable, there are some extra configurations to be taken into account.
|
||||
# The following options are available, assuming the engine is mounted as:
|
||||
#
|
||||
# mount MyEngine, at: '/my_engine'
|
||||
#
|
||||
# The router that invoked `devise_for`, in the example above, would be:
|
||||
# config.router_name = :my_engine
|
||||
#
|
||||
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
|
||||
# so you need to do it manually. For the users scope, it would be:
|
||||
# config.omniauth_path_prefix = '/my_engine/users/auth'
|
||||
|
||||
# ==> Turbolinks configuration
|
||||
# If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly:
|
||||
#
|
||||
# ActiveSupport.on_load(:devise_failure_app) do
|
||||
# include Turbolinks::Controller
|
||||
# end
|
||||
|
||||
# ==> Configuration for :registerable
|
||||
|
||||
# When set to false, does not sign a user in automatically after their password is
|
||||
# changed. Defaults to true, so a user is signed in automatically after changing a password.
|
||||
# config.sign_in_after_change_password = true
|
||||
end
|
||||
Devise::Async.setup do |config|
|
||||
config.enabled = true
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Configure parameters to be filtered from the log file. Use this to limit dissemination of
|
||||
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
|
||||
# notations and behaviors.
|
||||
Rails.application.config.filter_parameters += [
|
||||
:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
|
||||
]
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Heroicon.configure do |config|
|
||||
config.variant = :solid # Options are :solid, :outline and :mini
|
||||
|
||||
##
|
||||
# You can set a default class, which will get applied to every icon with
|
||||
# the given variant. To do so, un-comment the line below.
|
||||
# config.default_class = {solid: "h-5 w-5", outline: "h-6 w-6", mini: "h-4 w-4"}
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Add new inflection rules using the following format. Inflections
|
||||
# are locale specific, and you may define rules for as many different
|
||||
# locales as you wish. All of these examples are active by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.plural /^(ox)$/i, "\\1en"
|
||||
# inflect.singular /^(ox)en/i, "\\1"
|
||||
# inflect.irregular "person", "people"
|
||||
# inflect.uncountable %w( fish sheep )
|
||||
# end
|
||||
|
||||
# These inflection rules are supported but not enabled by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.acronym "RESTful"
|
||||
# end
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Kaminari.configure do |config|
|
||||
# config.default_per_page = 25
|
||||
# config.max_per_page = nil
|
||||
# config.window = 4
|
||||
# config.outer_window = 0
|
||||
# config.leaving = 0
|
||||
# config.right = 0
|
||||
# config.page_method_name = :page
|
||||
# config.param_name = :page
|
||||
# config.max_pages = nil
|
||||
# config.params_on_first_page = false
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
require "form_handler"
|
|
@ -0,0 +1,9 @@
|
|||
require "merged"
|
||||
|
||||
# directory inside /app/assets/images where the images are kept
|
||||
Merged.images_dir = "merged"
|
||||
|
||||
# directory where data and styles are kept
|
||||
# Notice that the data is ALWAYS inside a merged directory,
|
||||
# so in the default case Rails.root/merged/*.yml
|
||||
Merged.data_dir = "."
|
|
@ -0,0 +1,11 @@
|
|||
# Define an application-wide HTTP permissions policy. For further
|
||||
# information see https://developers.google.com/web/updates/2018/06/feature-policy
|
||||
#
|
||||
# Rails.application.config.permissions_policy do |f|
|
||||
# f.camera :none
|
||||
# f.gyroscope :none
|
||||
# f.microphone :none
|
||||
# f.usb :none
|
||||
# f.fullscreen :self
|
||||
# f.payment :self, "https://secure.example.com"
|
||||
# end
|
|
@ -0,0 +1,18 @@
|
|||
require "ransack"
|
||||
|
||||
Ransack.configure do |config|
|
||||
|
||||
config.custom_arrows = {
|
||||
up_arrow: '<div class="mt-1 ml-1 h-0 w-0 border-x-8 border-x-transparent border-b-[16px] border-b-blue-600"></div>',
|
||||
down_arrow: '<div class="mt-1 ml-1 h-0 w-0 border-x-8 border-x-transparent border-t-[16px] border-t-blue-600"></div>',
|
||||
}
|
||||
# Change default search parameter key name.
|
||||
# Default key name is :q
|
||||
config.search_key = :q
|
||||
|
||||
# Raise errors if a query contains an unknown predicate or attribute.
|
||||
# Default is true (do not raise error on unknown conditions).
|
||||
config.ignore_unknown_conditions = false
|
||||
|
||||
config.hide_sort_order_indicators = false
|
||||
end
|
|
@ -0,0 +1,210 @@
|
|||
# frozen_string_literal: true
|
||||
#
|
||||
# Uncomment this and change the path if necessary to include your own
|
||||
# components.
|
||||
# See https://github.com/heartcombo/simple_form#custom-components to know
|
||||
# more about custom components.
|
||||
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
||||
#
|
||||
# Use this setup block to configure all options available in SimpleForm.
|
||||
SimpleForm.setup do |config|
|
||||
# Wrappers are used by the form builder to generate a
|
||||
# complete input. You can remove any component from the
|
||||
# wrapper, change the order or even add your own to the
|
||||
# stack. The options given below are used to wrap the
|
||||
# whole input.
|
||||
|
||||
config.wrappers :default, tag: 'div', class: 'mt-2', error_class: '', valid_class: '' do |b|
|
||||
b.use :html5
|
||||
b.use :placeholder
|
||||
b.optional :maxlength
|
||||
b.optional :minlength
|
||||
b.optional :pattern
|
||||
b.optional :min_max
|
||||
b.optional :readonly
|
||||
|
||||
b.use :label, class: "block text-sm font-medium text-gray-700"
|
||||
b.use :input,
|
||||
class: 'appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm',
|
||||
error_class: 'block w-full pr-10 border-red-300 text-red-900 placeholder-red-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md'
|
||||
b.use :full_error, wrap_with: { tag: 'p', class: 'mt-2 text-sm text-red-600' }
|
||||
b.use :hint, wrap_with: { tag: :p, class: "mt-2 text-sm text-gray-500" }
|
||||
end
|
||||
|
||||
config.wrappers :prepend_string, tag: 'div', class: '', error_class: '', valid_class: '' do |b|
|
||||
b.use :html5
|
||||
b.use :placeholder
|
||||
b.optional :maxlength
|
||||
b.optional :minlength
|
||||
b.optional :pattern
|
||||
b.optional :min_max
|
||||
b.optional :readonly
|
||||
|
||||
b.use :label, class: "block text-sm font-medium text-gray-700"
|
||||
|
||||
b.wrapper tag: 'div', class: 'mt-4 flex rounded-md shadow-sm' do |d|
|
||||
d.use :prepend
|
||||
d.use :input,
|
||||
class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-r-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300",
|
||||
error_class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-r-md focus:ring-red-500 focus:border-red-500 sm:text-sm border-red-300 text-red-900 placeholder-red-300"
|
||||
end
|
||||
b.use :full_error, wrap_with: { tag: "p", class: "mt-2 text-sm text-red-600" }
|
||||
b.use :hint, wrap_with: { tag: :p, class: "mt-2 text-sm text-gray-500" }
|
||||
end
|
||||
|
||||
config.wrappers :append_string, tag: 'div', class: '', error_class: '', valid_class: '' do |b|
|
||||
b.use :html5
|
||||
b.use :placeholder
|
||||
b.optional :maxlength
|
||||
b.optional :minlength
|
||||
b.optional :pattern
|
||||
b.optional :min_max
|
||||
b.optional :readonly
|
||||
|
||||
b.use :label, class: "block text-sm font-medium text-gray-700"
|
||||
|
||||
b.wrapper tag: 'div', class: 'mt-1 flex rounded-md shadow-sm' do |d|
|
||||
d.use :input,
|
||||
class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-l-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300",
|
||||
error_class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-l-md focus:ring-red-500 focus:border-red-500 sm:text-sm border-red-300 text-red-900 placeholder-red-300"
|
||||
d.use :append
|
||||
end
|
||||
b.use :full_error, wrap_with: { tag: "p", class: "mt-2 text-sm text-red-600" }
|
||||
b.use :hint, wrap_with: { tag: :p, class: "mt-2 text-sm text-gray-500" }
|
||||
end
|
||||
|
||||
config.wrappers :corner_hint, tag: :div do |b|
|
||||
b.use :html5
|
||||
b.use :placeholder
|
||||
b.optional :maxlength
|
||||
b.optional :minlength
|
||||
b.optional :pattern
|
||||
b.optional :min_max
|
||||
b.optional :readonly
|
||||
|
||||
b.wrapper tag: :div, class: "flex justify-between", error_class: nil, valid_class: nil do |c|
|
||||
c.use :label, class: "block text-sm font-medium text-gray-700"
|
||||
c.use :hint, wrap_with: { tag: :span, class: "text-sm text-gray-500" }
|
||||
end
|
||||
|
||||
b.use :input,
|
||||
class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm",
|
||||
error_class: "block w-full pr-10 border-red-300 text-red-900 placeholder-red-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md"
|
||||
b.use :full_error, wrap_with: { tag: "p", class: "mt-2 text-sm text-red-600" }
|
||||
end
|
||||
|
||||
# The default wrapper to be used by the FormBuilder.
|
||||
config.default_wrapper = :default
|
||||
|
||||
# Define the way to render check boxes / radio buttons with labels.
|
||||
# Defaults to :nested for bootstrap config.
|
||||
# inline: input + label
|
||||
# nested: label > input
|
||||
config.boolean_style = :nested
|
||||
|
||||
# Default class for buttons
|
||||
config.button_class = nil
|
||||
|
||||
# Method used to tidy up errors. Specify any Rails Array method.
|
||||
# :first lists the first message for each field.
|
||||
# Use :to_sentence to list all errors for each field.
|
||||
# config.error_method = :first
|
||||
|
||||
# Default tag used for error notification helper.
|
||||
config.error_notification_tag = :div
|
||||
|
||||
# CSS class to add for error notification helper.
|
||||
config.error_notification_class = ''
|
||||
|
||||
# Series of attempts to detect a default label method for collection.
|
||||
# config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
|
||||
|
||||
# Series of attempts to detect a default value method for collection.
|
||||
# config.collection_value_methods = [ :id, :to_s ]
|
||||
|
||||
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
|
||||
# config.collection_wrapper_tag = nil
|
||||
|
||||
# You can define the class to use on all collection wrappers. Defaulting to none.
|
||||
# config.collection_wrapper_class = nil
|
||||
|
||||
# You can wrap each item in a collection of radio/check boxes with a tag,
|
||||
# defaulting to :span.
|
||||
# config.item_wrapper_tag = :span
|
||||
|
||||
# You can define a class to use in all item wrappers. Defaulting to none.
|
||||
# config.item_wrapper_class = nil
|
||||
|
||||
# How the label text should be generated altogether with the required text.
|
||||
config.label_text = lambda { |label, required, explicit_label| "#{label}" }
|
||||
|
||||
# You can define the class to use on all labels. Default is nil.
|
||||
# config.label_class = nil
|
||||
|
||||
# You can define the default class to be used on forms. Can be overriden
|
||||
# with `html: { :class }`. Defaulting to none.
|
||||
config.default_form_class = nil
|
||||
config.form_class = nil
|
||||
|
||||
# You can define which elements should obtain additional classes
|
||||
config.generate_additional_classes_for = []
|
||||
|
||||
# Whether attributes are required by default (or not). Default is true.
|
||||
# config.required_by_default = true
|
||||
|
||||
# Tell browsers whether to use the native HTML5 validations (novalidate form option).
|
||||
# These validations are enabled in SimpleForm's internal config but disabled by default
|
||||
# in this configuration, which is recommended due to some quirks from different browsers.
|
||||
# To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
|
||||
# change this configuration to true.
|
||||
config.browser_validations = false
|
||||
|
||||
# Custom mappings for input types. This should be a hash containing a regexp
|
||||
# to match as key, and the input type that will be used when the field name
|
||||
# matches the regexp as value.
|
||||
# config.input_mappings = { /count/ => :integer }
|
||||
|
||||
# Custom wrappers for input types. This should be a hash containing an input
|
||||
# type as key and the wrapper that will be used for all inputs with specified type.
|
||||
config.wrapper_mappings = {
|
||||
string: :default,
|
||||
prepend_string: :prepend_string,
|
||||
append_string: :append_string,
|
||||
}
|
||||
|
||||
# Namespaces where SimpleForm should look for custom input classes that
|
||||
# override default inputs.
|
||||
# config.custom_inputs_namespaces << "CustomInputs"
|
||||
|
||||
# Default priority for time_zone inputs.
|
||||
# config.time_zone_priority = nil
|
||||
|
||||
# Default priority for country inputs.
|
||||
# config.country_priority = nil
|
||||
|
||||
# When false, do not use translations for labels.
|
||||
# config.translate_labels = true
|
||||
|
||||
# Automatically discover new inputs in Rails' autoload path.
|
||||
# config.inputs_discovery = true
|
||||
|
||||
# Cache SimpleForm inputs discovery
|
||||
# config.cache_discovery = !Rails.env.development?
|
||||
|
||||
# Default class for inputs
|
||||
# config.input_class = nil
|
||||
|
||||
# Define the default class of the input wrapper of the boolean input.
|
||||
config.boolean_label_class = 'checkbox'
|
||||
|
||||
# Defines if the default input wrapper class should be included in radio
|
||||
# collection wrappers.
|
||||
# config.include_default_input_wrapper_class = true
|
||||
|
||||
# Defines which i18n scope will be used in Simple Form.
|
||||
# config.i18n_scope = 'simple_form'
|
||||
|
||||
# Defines validation classes to the input_field. By default it's nil.
|
||||
# config.input_field_valid_class = 'is-valid'
|
||||
# config.input_field_error_class = 'is-invalid'
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
require 'sucker_punch/async_syntax'
|
|
@ -0,0 +1,191 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Thredded configuration
|
||||
|
||||
# ==> User Configuration
|
||||
# The name of the class your app uses for your users.
|
||||
# By default the engine will use 'User' but if you have another name
|
||||
# for your user class - change it here.
|
||||
Thredded.user_class = 'Member'
|
||||
|
||||
# User name column, used in @mention syntax and *must* be unique.
|
||||
# This is the column used to search for users' names if/when someone is @ mentioned.
|
||||
Thredded.user_name_column = :name
|
||||
|
||||
# User display name method, by default thredded uses the user_name_column defined above
|
||||
# You may want to use :to_s or some more elaborate method
|
||||
# Thredded.user_display_name_method = :to_s
|
||||
|
||||
# The path (or URL) you will use to link to your users' profiles.
|
||||
# When linking to a user, Thredded will use this lambda to spit out
|
||||
# the path or url to your user. This lambda is evaluated in the view context.
|
||||
# If the lambda returns nil, a span element is returned instead of a link; so
|
||||
# setting this to always return nil effectively disables all user links.
|
||||
Thredded.user_path = ->(user) {
|
||||
user_path = :"#{Thredded.user_class_name.demodulize.underscore}_path"
|
||||
main_app.respond_to?(user_path) ? main_app.send(user_path, user) : "/users/#{user.to_param}"
|
||||
}
|
||||
|
||||
# This method is used by Thredded controllers and views to fetch the currently signed-in user
|
||||
Thredded.current_user_method = :"current_#{Thredded.user_class_name.demodulize.underscore}"
|
||||
|
||||
# User avatar URL. rails_gravatar gem is used by default:
|
||||
Thredded.avatar_url = ->(user) { RailsGravatar.src(user.email, 156, 'mm') }
|
||||
|
||||
# ==> Permissions Configuration
|
||||
# By default, thredded uses a simple permission model, where all the users can post to all message boards,
|
||||
# and admins and moderators are determined by a flag on the users table.
|
||||
|
||||
# The name of the moderator flag column on the users table.
|
||||
Thredded.moderator_column = :admin
|
||||
# The name of the admin flag column on the users table.
|
||||
Thredded.admin_column = :admin
|
||||
|
||||
# Whether posts and topics pending moderation are visible to regular users.
|
||||
Thredded.content_visible_while_pending_moderation = true
|
||||
|
||||
# This model can be customized further by overriding a handful of methods on the User model.
|
||||
# For more information, see app/models/thredded/user_extender.rb.
|
||||
|
||||
# ==> UI configuration
|
||||
|
||||
# How to calculate the position of messageboards in a list:
|
||||
# :position (default) set the position manually (new messageboards go to the bottom, by creation timestamp)
|
||||
# :last_post_at_desc most recent post first
|
||||
# :topics_count_desc most topics first
|
||||
Thredded.messageboards_order = :position
|
||||
|
||||
# Whether admin users see button to delete entire messageboards on the messageboard edit page.
|
||||
Thredded.show_messageboard_delete_button = false
|
||||
|
||||
# Whether MessageboardGroup show page is enabled.
|
||||
Thredded.show_messageboard_group_page = true
|
||||
|
||||
# Whether users that are following a topic are listed on the topic page.
|
||||
Thredded.show_topic_followers = false
|
||||
|
||||
# Whether the list of users who are currently online is displayed.
|
||||
Thredded.currently_online_enabled = true
|
||||
|
||||
# Whether private messaging functionality is enabled.
|
||||
Thredded.private_messaging_enabled = true
|
||||
|
||||
# The number of topics to display per page.
|
||||
# Thredded.topics_per_page = 50
|
||||
|
||||
# The number of posts to display per page in a topic.
|
||||
# Thredded.posts_per_page = 25
|
||||
|
||||
# The layout for rendering Thredded views.
|
||||
Thredded.layout = 'thredded_layout'
|
||||
|
||||
# ==> Email Configuration
|
||||
# Email "From:" field will use the following
|
||||
# (this is also used as the "To" address for both email notifcations, as all the recipients are on bcc)
|
||||
# Thredded.email_from = 'no-reply@example.com'
|
||||
|
||||
# Emails going out will prefix the "Subject:" with the following string
|
||||
# Thredded.email_outgoing_prefix = '[My Forum] '
|
||||
#
|
||||
# The parent mailer for all Thredded mailers
|
||||
# Thredded.parent_mailer = 'ActionMailer::Base'
|
||||
|
||||
# ==> Model configuration
|
||||
# The range of valid messageboard name lengths. Default:
|
||||
# Thredded.messageboard_name_length_range = (1..60)
|
||||
#
|
||||
# The range of valid topic title lengths. Default:
|
||||
# Thredded.topic_title_length_range = (1..200)
|
||||
|
||||
# ==> Routes and URLs
|
||||
# How Thredded generates URL slugs from text:
|
||||
|
||||
# Default:
|
||||
# Thredded.slugifier = ->(input) { input.parameterize }
|
||||
|
||||
# If your forum is in a language other than English, you might want to use the babosa gem instead
|
||||
# Thredded.slugifier = ->(input) { Babosa::Identifier.new(input).normalize.transliterate(:russian).to_s }
|
||||
|
||||
# By default, thredded uses integers for record ID route constraints.
|
||||
# For integer based IDs (default):
|
||||
# Thredded.routes_id_constraint = /[1-9]\d*/
|
||||
#
|
||||
# For UUID based IDs (example):
|
||||
# Thredded.routes_id_constraint = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
|
||||
|
||||
# ==> Post Content Formatting
|
||||
# Customize the way Thredded handles post formatting.
|
||||
|
||||
# ===> Emoji using the 'gemoji' gem
|
||||
# 1. Install `gemoji` following instruction at https://github.com/github/gemoji.
|
||||
# 2. Uncomment the following line:
|
||||
# Thredded::ContentFormatter.after_markup_filters.insert(1, HTML::Pipeline::EmojiFilter)
|
||||
|
||||
# Change the HTML sanitization settings used by Thredded.
|
||||
# See the Sanitize docs for more information on the underlying library: https://github.com/rgrove/sanitize/#readme
|
||||
# E.g. to allow a custom element <custom-element>:
|
||||
# Thredded::ContentFormatter.allowlist[:elements] += %w(custom-element)
|
||||
|
||||
# ==> User autocompletion (Private messages and @-mentions)
|
||||
# Thredded.autocomplete_min_length = 2 lower to 1 if have 1-letter names -- increase if you want
|
||||
|
||||
# ==> Error Handling
|
||||
# By default Thredded just renders a flash alert on errors such as Topic not found, or Login required.
|
||||
# Below is an example of overriding the default behavior on LoginRequired:
|
||||
#
|
||||
# Rails.application.config.to_prepare do
|
||||
# Thredded::ApplicationController.module_eval do
|
||||
# # Render sign in page:
|
||||
# rescue_from Thredded::Errors::LoginRequired do |exception|
|
||||
# flash.now[:notice] = exception.message
|
||||
# controller = Users::SessionsController.new
|
||||
# controller.request = request
|
||||
# controller.request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
# controller.response = response
|
||||
# controller.response_options = { status: :forbidden }
|
||||
# controller.process(:new)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
# ==> View hooks
|
||||
#
|
||||
# Customize the UI before/after/replacing individual components.
|
||||
# See the full list of view hooks and their arguments by running:
|
||||
#
|
||||
# $ grep view_hooks -R --include '*.html.erb' "$(bundle show thredded)"
|
||||
#
|
||||
# Rails.application.config.to_prepare do
|
||||
# Thredded.view_hooks.post_form.content_text_area.config.before do |form:, **args|
|
||||
# # This is called in the Thredded view context, so all Thredded helpers and URLs are accessible here directly.
|
||||
# 'hi'
|
||||
# end
|
||||
# end
|
||||
|
||||
# ==> Topic following
|
||||
#
|
||||
# By default, a user will be subscribed to a topic they've created. Uncomment this to not subscribe them:
|
||||
#
|
||||
# Thredded.auto_follow_when_creating_topic = false
|
||||
#
|
||||
# By default, a user will be subscribed to (follow) a topic they post in. Uncomment this to not subscribe them:
|
||||
#
|
||||
# Thredded.auto_follow_when_posting_in_topic = false
|
||||
#
|
||||
# By default, a user will be subscribed to the topic they get @-mentioned in.
|
||||
# Individual users can disable this in the Notification Settings.
|
||||
# To change the default for all users, simply change the default value of the `follow_topics_on_mention` column
|
||||
# of the `thredded_user_preferences` and `thredded_user_messageboard_preferences` tables.
|
||||
|
||||
# ==> Notifiers
|
||||
#
|
||||
# Change how users can choose to be notified, by adding notifiers here, or removing the initializer altogether
|
||||
#
|
||||
# default:
|
||||
# Thredded.notifiers = [Thredded::EmailNotifier.new]
|
||||
#
|
||||
# none:
|
||||
# Thredded.notifiers = []
|
||||
#
|
||||
# add in (must install separate gem (under development) as well):
|
||||
# Thredded.notifiers = [Thredded::EmailNotifier.new, Thredded::PushoverNotifier.new(ENV['PUSHOVER_APP_ID'])]
|
|
@ -0,0 +1,65 @@
|
|||
# Additional translations at https://github.com/heartcombo/devise/wiki/I18n
|
||||
|
||||
en:
|
||||
devise:
|
||||
confirmations:
|
||||
confirmed: "Your email address has been successfully confirmed."
|
||||
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
|
||||
failure:
|
||||
already_authenticated: "You are already signed in."
|
||||
inactive: "Your account is not activated yet."
|
||||
invalid: "Invalid %{authentication_keys} or password."
|
||||
locked: "Your account is locked."
|
||||
last_attempt: "You have one more attempt before your account is locked."
|
||||
not_found_in_database: "Invalid %{authentication_keys} or password."
|
||||
timeout: "Your session expired. Please sign in again to continue."
|
||||
unauthenticated: "You need to sign in or sign up before continuing."
|
||||
unconfirmed: "You have to confirm your email address before continuing."
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: "Confirmation instructions"
|
||||
reset_password_instructions:
|
||||
subject: "Reset password instructions"
|
||||
unlock_instructions:
|
||||
subject: "Unlock instructions"
|
||||
email_changed:
|
||||
subject: "Email Changed"
|
||||
password_change:
|
||||
subject: "Password Changed"
|
||||
omniauth_callbacks:
|
||||
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
|
||||
success: "Successfully authenticated from %{kind} account."
|
||||
passwords:
|
||||
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
||||
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
updated: "Your password has been changed successfully. You are now signed in."
|
||||
updated_not_active: "Your password has been changed successfully."
|
||||
registrations:
|
||||
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
|
||||
signed_up: "Welcome! You have signed up successfully."
|
||||
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
|
||||
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
|
||||
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
|
||||
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
|
||||
updated: "Your account has been updated successfully."
|
||||
updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
|
||||
sessions:
|
||||
signed_in: "Signed in successfully."
|
||||
signed_out: "Signed out successfully."
|
||||
already_signed_out: "Signed out successfully."
|
||||
unlocks:
|
||||
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
|
||||
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
|
||||
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
|
||||
errors:
|
||||
messages:
|
||||
already_confirmed: "was already confirmed, please try signing in"
|
||||
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
|
||||
expired: "has expired, please request a new one"
|
||||
not_found: "not found"
|
||||
not_locked: "was not locked"
|
||||
not_saved:
|
||||
one: "1 error prohibited this %{resource} from being saved:"
|
||||
other: "%{count} errors prohibited this %{resource} from being saved:"
|
|
@ -0,0 +1,33 @@
|
|||
# Files in the config/locales directory are used for internationalization
|
||||
# and are automatically loaded by Rails. If you want to use locales other
|
||||
# than English, add the necessary files in this directory.
|
||||
#
|
||||
# To use the locales, use `I18n.t`:
|
||||
#
|
||||
# I18n.t "hello"
|
||||
#
|
||||
# In views, this is aliased to just `t`:
|
||||
#
|
||||
# <%= t("hello") %>
|
||||
#
|
||||
# To use a different locale, set it with `I18n.locale`:
|
||||
#
|
||||
# I18n.locale = :es
|
||||
#
|
||||
# This would use the information in config/locales/es.yml.
|
||||
#
|
||||
# The following keys must be escaped otherwise they will not be retrieved by
|
||||
# the default I18n backend:
|
||||
#
|
||||
# true, false, on, off, yes, no
|
||||
#
|
||||
# Instead, surround them with single quotes.
|
||||
#
|
||||
# en:
|
||||
# "true": "foo"
|
||||
#
|
||||
# To learn more, please read the Rails Internationalization guide
|
||||
# available at https://guides.rubyonrails.org/i18n.html.
|
||||
|
||||
en:
|
||||
hello: "Hello world"
|
|
@ -0,0 +1,18 @@
|
|||
Rails.application.routes.draw do
|
||||
resources :pictures
|
||||
resources :stories
|
||||
|
||||
devise_for :members ,controllers: { registrations: 'registrations' }
|
||||
devise_scope :member do
|
||||
get "/members/edit_email" , to: "registrations#edit_email"
|
||||
end
|
||||
|
||||
get "timeline" , to: "timeline#index"
|
||||
|
||||
resources :members
|
||||
|
||||
mount Thredded::Engine => '/forum'
|
||||
|
||||
merged_routes root: true
|
||||
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
test:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("tmp/storage") %>
|
||||
|
||||
local:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("storage") %>
|
|
@ -0,0 +1,70 @@
|
|||
const defaultTheme = require('tailwindcss/defaultTheme')
|
||||
|
||||
const execSync = require('child_process').execSync;
|
||||
const output = execSync('bundle show merged', { encoding: 'utf-8' });
|
||||
const fullname = output.trim() + '/**/*.{haml,html,rb}' ;
|
||||
|
||||
const output2 = execSync('bundle show simple_form_tailwind_css', { encoding: 'utf-8' });
|
||||
const fullname2 = output2.trim() + '/lib/**/*.rb' ;
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
'./public/*.html',
|
||||
'./app/helpers/**/*.rb',
|
||||
'./config/initializers/**/*.rb',
|
||||
'./app/javascript/**/*.js',
|
||||
'./app/views/**/*.{erb,haml,html,slim}' ,
|
||||
fullname , fullname2
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
typography: ({ theme }) => ({
|
||||
inherit: {
|
||||
css: {
|
||||
'--tw-prose-body': 'inherit' ,
|
||||
'--tw-prose-headings': 'inherit',
|
||||
'--tw-prose-lead': 'inherit' ,
|
||||
'--tw-prose-links': 'inherit' ,
|
||||
'--tw-prose-bold': 'inherit' ,
|
||||
'--tw-prose-counters': 'inherit' ,
|
||||
'--tw-prose-bullets': 'inherit' ,
|
||||
'--tw-prose-hr': 'inherit' ,
|
||||
'--tw-prose-quotes': 'inherit' ,
|
||||
'--tw-prose-quote-borders': 'inherit' ,
|
||||
'--tw-prose-captions': 'inherit' ,
|
||||
'--tw-prose-code': 'inherit' ,
|
||||
'--tw-prose-pre-code': 'inherit' ,
|
||||
'--tw-prose-pre-bg': 'inherit' ,
|
||||
'--tw-prose-th-borders': 'inherit' ,
|
||||
'--tw-prose-td-borders': 'inherit' ,
|
||||
'--tw-prose-invert-body': 'inherit' ,
|
||||
'--tw-prose-invert-headings': 'inherit',
|
||||
'--tw-prose-invert-lead': 'inherit' ,
|
||||
'--tw-prose-invert-links': 'inherit',
|
||||
'--tw-prose-invert-bold': 'inherit',
|
||||
'--tw-prose-invert-counters': 'inherit' ,
|
||||
'--tw-prose-invert-bullets': 'inherit' ,
|
||||
'--tw-prose-invert-hr': 'inherit' ,
|
||||
'--tw-prose-invert-quotes': 'inherit' ,
|
||||
'--tw-prose-invert-quote-borders': 'inherit' ,
|
||||
'--tw-prose-invert-captions': 'inherit' ,
|
||||
'--tw-prose-invert-code': 'inherit',
|
||||
'--tw-prose-invert-pre-code': 'inherit' ,
|
||||
'--tw-prose-invert-pre-bg': 'inherit',
|
||||
'--tw-prose-invert-th-borders': 'inherit' ,
|
||||
'--tw-prose-invert-td-borders': 'inherit' ,
|
||||
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/forms'),
|
||||
require('@tailwindcss/aspect-ratio'),
|
||||
require('@tailwindcss/typography'),
|
||||
]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
class CreateMembers < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :members do |t|
|
||||
t.string :name
|
||||
t.string :bio
|
||||
t.string :picture
|
||||
t.boolean :public
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,51 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDeviseToMembers < ActiveRecord::Migration[7.0]
|
||||
def self.up
|
||||
change_table :members do |t|
|
||||
## Database authenticatable
|
||||
t.string :email, null: false, default: ""
|
||||
t.string :encrypted_password, null: false, default: ""
|
||||
|
||||
## Recoverable
|
||||
t.string :reset_password_token
|
||||
t.datetime :reset_password_sent_at
|
||||
|
||||
## Rememberable
|
||||
t.datetime :remember_created_at
|
||||
|
||||
## Trackable
|
||||
# t.integer :sign_in_count, default: 0, null: false
|
||||
# t.datetime :current_sign_in_at
|
||||
# t.datetime :last_sign_in_at
|
||||
# t.string :current_sign_in_ip
|
||||
# t.string :last_sign_in_ip
|
||||
|
||||
## Confirmable
|
||||
t.string :confirmation_token
|
||||
t.datetime :confirmed_at
|
||||
t.datetime :confirmation_sent_at
|
||||
t.string :unconfirmed_email # Only if using reconfirmable
|
||||
|
||||
## Lockable
|
||||
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
||||
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
||||
# t.datetime :locked_at
|
||||
|
||||
|
||||
# Uncomment below if timestamps were not included in your original model.
|
||||
# t.timestamps null: false
|
||||
end
|
||||
|
||||
add_index :members, :email, unique: true
|
||||
add_index :members, :reset_password_token, unique: true
|
||||
# add_index :members, :confirmation_token, unique: true
|
||||
# add_index :members, :unlock_token, unique: true
|
||||
end
|
||||
|
||||
def self.down
|
||||
# By default, we don't want to make any assumption about how to roll back a migration when your
|
||||
# model already existed. Please edit below which fields you would like to remove in this migration.
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
class CreateStories < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :stories do |t|
|
||||
t.references :member
|
||||
t.string :picture
|
||||
t.string :header
|
||||
t.text :text
|
||||
t.date :happened
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class CreatePictures < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :pictures do |t|
|
||||
t.string :picture
|
||||
t.string :text
|
||||
t.date :happened
|
||||
t.references :member, null: false, foreign_key: true
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# This file is the source Rails uses to define your schema when running `bin/rails
|
||||
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_01_25_172223) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
create_table "members", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "bio"
|
||||
t.string "picture"
|
||||
t.boolean "public"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "email", default: "", null: false
|
||||
t.string "encrypted_password", default: "", null: false
|
||||
t.string "reset_password_token"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.string "confirmation_token"
|
||||
t.datetime "confirmed_at"
|
||||
t.datetime "confirmation_sent_at"
|
||||
t.string "unconfirmed_email"
|
||||
t.index ["email"], name: "index_members_on_email", unique: true
|
||||
t.index ["reset_password_token"], name: "index_members_on_reset_password_token", unique: true
|
||||
end
|
||||
|
||||
create_table "pictures", force: :cascade do |t|
|
||||
t.string "picture"
|
||||
t.string "text"
|
||||
t.date "happened"
|
||||
t.bigint "member_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["member_id"], name: "index_pictures_on_member_id"
|
||||
end
|
||||
|
||||
create_table "stories", force: :cascade do |t|
|
||||
t.bigint "member_id"
|
||||
t.string "picture"
|
||||
t.string "header"
|
||||
t.text "text"
|
||||
t.date "happened"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["member_id"], name: "index_stories_on_member_id"
|
||||
end
|
||||
|
||||
add_foreign_key "pictures", "members"
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
# This file should contain all the record creation needed to seed the database with its default values.
|
||||
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }])
|
||||
# Character.create(name: "Luke", movie: movies.first)
|
|
@ -0,0 +1,10 @@
|
|||
class FormHandler
|
||||
|
||||
def handle_form(section , data )
|
||||
puts "Section on page : #{section.page.name}"
|
||||
data.each do |name , value|
|
||||
puts "#{name}: #{value}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
--- []
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
- :id: 1
|
||||
:header: Name
|
||||
:text: ''
|
||||
:options:
|
||||
compulsory: 'yes'
|
||||
form_type: text
|
||||
:updated_at: &1 2022-12-09 17:56:51.141334688 +02:00
|
||||
:section_id: 9
|
||||
:index: 1
|
||||
:image_id:
|
||||
- :id: 2
|
||||
:header: Email
|
||||
:text: ''
|
||||
:options:
|
||||
compulsory: 'yes'
|
||||
form_type: email
|
||||
:updated_at: *1
|
||||
:section_id: 9
|
||||
:index: 2
|
||||
:image_id:
|
||||
- :id: 3
|
||||
:header: Phone
|
||||
:text: ''
|
||||
:options:
|
||||
compulsory: 'yes'
|
||||
form_type: phone
|
||||
:updated_at: *1
|
||||
:section_id: 9
|
||||
:index: 3
|
||||
:image_id:
|
||||
- :id: 4
|
||||
:header: Interest
|
||||
:text: ''
|
||||
:updated_at: *1
|
||||
:section_id: 9
|
||||
:index: 4
|
||||
:image_id:
|
||||
:options: {}
|
||||
- :id: 5
|
||||
:header: Message
|
||||
:text: ''
|
||||
:options:
|
||||
compulsory: 'no'
|
||||
form_type: message
|
||||
:updated_at: *1
|
||||
:section_id: 9
|
||||
:index: 5
|
||||
:image_id:
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
- :name: 3dprinter
|
||||
:type: webp
|
||||
:width: 1279
|
||||
:height: 457
|
||||
:created_at: 2022-12-07 14:26:04.321730558 +02:00
|
||||
:size: 63
|
||||
:id: 1
|
||||
:tags: wide
|
||||
- :name: Clay
|
||||
:type: webp
|
||||
:width: 1279
|
||||
:height: 401
|
||||
:created_at: 2022-12-07 14:51:55.996653796 +02:00
|
||||
:size: 95
|
||||
:id: 3
|
||||
:tags: wide
|
||||
- :name: Electronics
|
||||
:type: webp
|
||||
:width: 1279
|
||||
:height: 401
|
||||
:created_at: 2022-12-07 14:50:32.948094206 +02:00
|
||||
:size: 96
|
||||
:id: 11
|
||||
:tags: wide
|
||||
- :name: Map
|
||||
:type: png
|
||||
:width: 2169
|
||||
:height: 1149
|
||||
:created_at: 2022-12-08 18:56:09.781331767 +02:00
|
||||
:size: 1020
|
||||
:id: 22
|
||||
:tags: wide
|
||||
- :name: Metal
|
||||
:type: webp
|
||||
:width: 782
|
||||
:height: 308
|
||||
:created_at: 2022-12-07 14:48:52.388838324 +02:00
|
||||
:size: 43
|
||||
:id: 23
|
||||
:tags: wide
|
||||
- :name: Sowing
|
||||
:type: webp
|
||||
:width: 780
|
||||
:height: 262
|
||||
:created_at: 2022-12-07 14:27:36.943099639 +02:00
|
||||
:size: 28
|
||||
:id: 33
|
||||
:tags: wide
|
||||
- :name: Woodworking
|
||||
:type: webp
|
||||
:width: 1279
|
||||
:height: 415
|
||||
:created_at: 2022-12-07 14:52:58.521569352 +02:00
|
||||
:size: 102
|
||||
:id: 40
|
||||
:tags: wide
|
||||
- :name: house icon 1
|
||||
:type: png
|
||||
:tags: ''
|
||||
:id: 45
|
||||
:width: 450
|
||||
:height: 423
|
||||
:size: 13
|
||||
:updated_at: 2023-01-14 16:01:33.073509683 +02:00
|
||||
:updated_by: maijanposteja@gmail.com
|
||||
- :name: wall painting
|
||||
:type: jpg
|
||||
:tags: ''
|
||||
:width: 990
|
||||
:height: 1483
|
||||
:size: 627
|
||||
:id: 73
|
||||
:updated_at: 2023-03-24 20:48:39.675000054 +02:00
|
||||
:updated_by: maijanposteja@gmail.com
|
||||
- :name: audio_video
|
||||
:type: jpg
|
||||
:tags: ''
|
||||
:width: 1080
|
||||
:height: 486
|
||||
:size: 94
|
||||
:id: 119
|
||||
:updated_at: 2023-08-12 22:15:39.814942708 +03:00
|
||||
:updated_by: torsten@villataika.fi
|
|
@ -0,0 +1 @@
|
|||
--- []
|
|
@ -0,0 +1 @@
|
|||
--- []
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
- :name: index
|
||||
:updated_at: 2022-12-09 17:56:51.141334688 +02:00
|
||||
:id: 1
|
||||
:type: page
|
||||
:options: {}
|
||||
- :name: code_of_conduct
|
||||
:updated_at: 2023-02-16 21:35:14.776048574 +02:00
|
||||
:type: page
|
||||
:updated_by: torsten@villataika.fi
|
||||
:id: 10
|
|
@ -0,0 +1 @@
|
|||
--- []
|
|
@ -0,0 +1,403 @@
|
|||
---
|
||||
- :template: section_full_up
|
||||
:header: Makerspace
|
||||
:text: "A makerspace gives everyone the capabilities to create with many different
|
||||
materials. It is the modern day library, where we don't each have to own, but
|
||||
share the equipment.\r\nIn Finland this builds on the traditional adult education
|
||||
and expands it into new technologies like electronics and 3d printing.\r\n\r\nWe
|
||||
have started with traditional tools that we know and have, like woodworking, sowing,
|
||||
and metalworking. And expanded into electronics and 3d technologies, with more
|
||||
tools coming all the time.\r\n\r\nCurrently a unified space is under construction
|
||||
and part of the tools are distributed throughout the house. But a lot exists already.
|
||||
\r\n"
|
||||
:image_name: makerspace
|
||||
:id: 1
|
||||
:updated_at: 2023-10-20 22:06:42.698518991 +03:00
|
||||
:page_id: 1
|
||||
:index: 1
|
||||
:options:
|
||||
order: left
|
||||
background: white
|
||||
text_color: none
|
||||
subheader: ''
|
||||
text: ''
|
||||
text_align: center
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:image_id: 0
|
||||
:updated_by: torsten@villataika.fi
|
||||
:card_template: ''
|
||||
- :template: section_large_image
|
||||
:id: 3
|
||||
:header: 3D
|
||||
:text: "We have three 3d printers, small, medium and large, to allow everyone to
|
||||
try to bring their imagination to the physical world.\r\n\r\nWe have converted
|
||||
all printers to klipper software, for easy use, but powerful features.\r\n\r\nComputers
|
||||
and software for designing are available."
|
||||
:options:
|
||||
subheader: Printing, scanning and planning
|
||||
order: right
|
||||
text_color: solid_black
|
||||
background: light_gray
|
||||
margin: none
|
||||
text_align: left
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:image_name: 3dprinter_wide
|
||||
:updated_at: 2023-08-12 22:08:27.832393532 +03:00
|
||||
:page_id: 1
|
||||
:index: 4
|
||||
:image_id: 1
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: section_large_image
|
||||
:id: 4
|
||||
:header: Clothes
|
||||
:text: "The fourth floor already has some four sowing machines We are sourcing industrial
|
||||
sawing and embroidering machines so no project is too big (or small). The large
|
||||
rooms is set up for a shared working environment, enabling knowledge to be shared
|
||||
easily.\r\nPrivate lockers make it easy to interrupt and return to your project
|
||||
in your own time."
|
||||
:image_name: sowing_wide
|
||||
:options:
|
||||
subheader: Express your style
|
||||
order: left
|
||||
text_color: none
|
||||
background: light_gray
|
||||
margin: none
|
||||
text_align: left
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:updated_at: 2023-08-12 22:09:09.406872587 +03:00
|
||||
:page_id: 1
|
||||
:index: 7
|
||||
:image_id: 33
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: section_large_image
|
||||
:id: 5
|
||||
:header: Metal workshop and garage
|
||||
:text: "The building has a garage workshop (not as clean as the picture) and we
|
||||
have moved our metal workshop there. There is a saw, drills, different welders
|
||||
(gas, stick, tig) and wrenches to build the robot of your dreams, or fix a car
|
||||
(on the car lift).\r\n\r\nWe have also got a metal lathe and milling machine,
|
||||
though they are not set up yet."
|
||||
:image_name: metal_wide
|
||||
:options:
|
||||
subheader: Useful and practical
|
||||
margin: none
|
||||
order: left
|
||||
text_color: none
|
||||
background: light_gray
|
||||
:updated_at: 2023-08-10 17:53:51.223572115 +03:00
|
||||
:page_id: 1
|
||||
:index: 3
|
||||
:image_id: 23
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: section_large_image
|
||||
:id: 6
|
||||
:header: Electronics
|
||||
:text: "This is in the third floor, set up as a basic electronics workshop.\r\nCurrently
|
||||
we only have a soldering iron and a lab power source, but we are hoping to buy
|
||||
oscilloscopes and other measuring equipment that will allow members to do everything
|
||||
from a small LED project to arduino or raspberry pi based robots."
|
||||
:image_name: electronics_wide
|
||||
:options:
|
||||
subheader: Wizz wizz wizz
|
||||
margin: none
|
||||
order: left
|
||||
text_color: none
|
||||
background: light_gray
|
||||
text_align: left
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:updated_at: 2023-08-12 22:08:42.987989016 +03:00
|
||||
:page_id: 1
|
||||
:index: 5
|
||||
:image_id: 11
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: section_large_image
|
||||
:id: 7
|
||||
:header: Clay
|
||||
:text: "Hub Feenix also has a clay oven and a turning table. These are in two wet
|
||||
spaces currently also in the fourth floor.\r\n"
|
||||
:image_name: clay_wide
|
||||
:options:
|
||||
subheader: Sculptured or turned
|
||||
margin: none
|
||||
order: right
|
||||
text_color: none
|
||||
background: light_gray
|
||||
text_align: left
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:updated_at: 2023-08-12 22:09:18.211745260 +03:00
|
||||
:page_id: 1
|
||||
:index: 8
|
||||
:image_id: 3
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: section_large_image
|
||||
:id: 8
|
||||
:header: Woodworking and Saw
|
||||
:text: "We have a full woodworking workshop, everything from hand tools to a small
|
||||
saw-mill.\r\n\r\nThe space is around 300m2 and the outside area about 3000. We
|
||||
have a big table saw, both planers, chops saws and hand tools to do just about
|
||||
every project.\r\n\r\nWith the woodmizer saw mill we make beams and boards. And
|
||||
since we have enough space we can dry some of that inside. Also we have started
|
||||
to build a tiny-house and other structures for the hub. "
|
||||
:image_name: woodworking_wide
|
||||
:options:
|
||||
subheader: ''
|
||||
margin: none
|
||||
order: right
|
||||
text_color: none
|
||||
background: light_gray
|
||||
:updated_at: 2023-08-10 17:51:23.308241092 +03:00
|
||||
:page_id: 1
|
||||
:index: 2
|
||||
:image_id: 40
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: form_section
|
||||
:id: 9
|
||||
:card_template: form_field
|
||||
:header: Participate
|
||||
:text: "If you want to use any of the facilities or machines listed above, all you
|
||||
need to do is a certain amount of participation in general tasks.\r\nIn other
|
||||
words, the only charge is your time, and off course materials you use.\r\nAdditionally
|
||||
some machines will require skill to operate, and you need to prove that you are
|
||||
able, possibly participate in training.\r\n\r\nConsumables, like wood, thread,
|
||||
clay, electronic parts, cost but many basic ones are made available at cost price
|
||||
by the Hub.\r\n\r\nIf you want to come to look at the facilities, or find out
|
||||
more, you can fill out the form and we will get back to you."
|
||||
:options:
|
||||
ok_message: ''
|
||||
handler: FormHandler
|
||||
background: light_orange
|
||||
text_color: solid_black
|
||||
:updated_at: 2023-08-12 22:22:29.120421766 +03:00
|
||||
:page_id: 1
|
||||
:index: 9
|
||||
:image_id:
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: section_full_image
|
||||
:id: 28
|
||||
:header: Hub Feenix
|
||||
:text: "\r\nArt, craft, music, yoga, dance, meditation, nature, and creatives of
|
||||
every kind come together under our roof in an atmosphere of openness and learning. \r\n\r\n We
|
||||
are very much just starting, so make contact, check later, or follow us on facebook."
|
||||
:options:
|
||||
fixed: 'off'
|
||||
text_color: white
|
||||
text_align: left
|
||||
shade_color: solid_blue_25
|
||||
item_align: left
|
||||
image_align: right
|
||||
:image_name: cafe_about
|
||||
:updated_at: 2023-01-29 14:09:45.994009649 +02:00
|
||||
:page_id: 5
|
||||
:index: 1
|
||||
:image_id: 2
|
||||
:updated_by: maijanposteja@gmail.com
|
||||
- :template: section_full_up
|
||||
:id: 29
|
||||
:header: About Us
|
||||
:text: "Hub Feenix is a community space that fosters creativity, healing, and connection.
|
||||
\r\nArt, craft, music, yoga, dance, meditation, nature, and creative people of
|
||||
all kinds come together under our roof in an atmosphere of openness and learning.
|
||||
\r\n\r\nHub Feenix provides opportunities for creative people to live, work, learn,
|
||||
create, exhibit, and perform in a healing natural setting in the tranquil southeastern
|
||||
Finland forest. \r\n\r\nAs part of our commitment to ongoing connection and learning,
|
||||
Hub Feenix provides space for retreats, workshops, conferences, short- and long-term
|
||||
residencies, and other gatherings."
|
||||
:options:
|
||||
background: light_orange
|
||||
text_color: solid_blue
|
||||
margin: none
|
||||
subheader: ''
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
text_align: center
|
||||
item_align: center
|
||||
:updated_at: 2022-12-08 19:11:48.243621696 +02:00
|
||||
:page_id: 5
|
||||
:index: 2
|
||||
:image_id:
|
||||
- :template: section_full_image
|
||||
:id: 30
|
||||
:header: The road to Feenix
|
||||
:text: "[Click here to open](https://duckduckgo.com/?t=ffab&q=H%C3%B6gbenintie+30%2C+10350+Meltola%2C+Raasepori&atb=v283-1&ia=web&iaxm=directions&end=what%3AH%25C3%25B6gbensv%25C3%25A4gen%252030%252C%252010350%2520Meltola%252C%2520Finland&transport=drive)"
|
||||
:image_name: map_wide
|
||||
:options:
|
||||
fixed: 'on'
|
||||
text_color: black
|
||||
text_align: left
|
||||
shade_color: none
|
||||
item_align: left
|
||||
image_align: left
|
||||
:updated_at: 2023-01-01 14:19:06.708801219 +02:00
|
||||
:page_id: 5
|
||||
:index: 3
|
||||
:image_id: 22
|
||||
:updated_by: torsten@villataika.fi
|
||||
- :template: section_text
|
||||
:index: 4
|
||||
:page_id: 5
|
||||
:updated_at: 2023-03-21 17:30:10.029394454 +02:00
|
||||
:updated_by: maijanposteja@gmail.com
|
||||
:id: 41
|
||||
:options:
|
||||
text_columns: '2'
|
||||
background: light_orange
|
||||
text_color: none
|
||||
margin: none
|
||||
subheader: 'The birth of a community center '
|
||||
text_align: center
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:header: Our story
|
||||
:text: "Raisa Kaipainen and Torsten Ruger bought the old Meltola sanatorium on an
|
||||
auction site, April Fools´ day 1.4.2020 after three days notice. Surprised (and
|
||||
shocked) to have won the auction, we started creating an art community centre.
|
||||
\r\n\r\nThe plan to have a mix of creative endeavours and well being related events
|
||||
emerged quickly and thanks to the government we had lots of time to implement
|
||||
the ideas. \r\n\r\nWe created a non profit, Osuuskunta Hub Feenix, to take over
|
||||
the running of the activities. And by beginning of 2023 we now have 6 event spaces,
|
||||
100 beds, local artists and an international artists residency started.\r\n\r\nWith
|
||||
lots of care and time (and paint!) the place has become what many people call
|
||||
homely :-)\r\n \r\nWork continues on the makerspace idea and the garden."
|
||||
- :template: section_text
|
||||
:index: 5
|
||||
:page_id: 5
|
||||
:updated_at: 2023-03-21 17:30:31.797432719 +02:00
|
||||
:updated_by: maijanposteja@gmail.com
|
||||
:id: 47
|
||||
:card_template: ''
|
||||
:options:
|
||||
text_columns: '3'
|
||||
background: light_orange
|
||||
text_color: none
|
||||
margin: none
|
||||
subheader: ''
|
||||
text_align: left
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:header: Our vision
|
||||
:text: "The whole 15 000m2 building with all its wings will be in active use. \r\n\r\nHub
|
||||
Feenix Cafe will be open throughout the year and serve lunch to people of the
|
||||
house as well as locals.\r\n\r\nThere will be 25 artists working in our art studios
|
||||
permanently, 10-15 artists in residence and 10-15 digital nomads living and working
|
||||
in Hub Feenix throughout the year.\r\n\r\nSeveral international events yearly:
|
||||
well-being, dance, art, sound healing, vegetarian food etc, 1-3 bigger festivals
|
||||
and weekend courses throughout the year.\r\n\r\nHub Feenix is an active member
|
||||
in Raasepori community, collaborating with the city, the local culture life and
|
||||
services.\r\n\r\nWe'll have permanently hired staff.\r\n\r\nUpstairs of the big
|
||||
kitchen offers great workspaces for many small-scale vegan food producers: seitan,
|
||||
fermented vegetables, kombucha, cakes, vegan cheeses, artisan bread etc.\r\n\r\nOur
|
||||
shop will be open every day and sell art, handicrafts, vegan food products etc
|
||||
made in Hub Feenix.\r\n\r\nMakerspace will offer workshops, courses and possibility
|
||||
to use a wide range of tools and equipment for locals and international guests.\r\n\r\n30%
|
||||
of our energy will come from solar power and heating partly from geothermal heat.
|
||||
Also our own wood chip heating system will be developed forward.\r\n\r\nThere
|
||||
will be about 50 people living in the area of the Hub Feenix Village permanently.\r\n\r\nThe
|
||||
forests around Hub Feenix will be protected and taken care of naturally. They
|
||||
can be enjoyed by anyone who wants to refresh and exercise outdoors.\r\n\r\nThe
|
||||
Hub Feenix horse stable will keep taking our guests and locals for riding treks
|
||||
in the forest and offer animal assisted activities.\r\n\r\nAn outdoor yoga deck
|
||||
will be built soon. All around Hub Feenix there will be a flowering garden with
|
||||
fountains and places to sit in peace and enjoy the surroundings.\r\n\r\n\r\n"
|
||||
- :template: section_text
|
||||
:index: 1
|
||||
:page_id: 10
|
||||
:updated_at: 2023-09-12 19:31:36.747714983 +03:00
|
||||
:updated_by: maijanposteja@gmail.com
|
||||
:id: 51
|
||||
:card_template: ''
|
||||
:options:
|
||||
text_columns: '3'
|
||||
background: light_blue
|
||||
text_color: solid_black
|
||||
margin: none
|
||||
subheader: ''
|
||||
text_align: left
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:header: Code of Conduct
|
||||
:text: "Hub Feenix is a non-profit community and co-operation, that promotes creativity,
|
||||
wellbeing and continuous learning. Hub’s own values are love of life, fairness,
|
||||
constant learning of new things and giving to life.\r\n\r\nThese common rules
|
||||
have been created, so that everyone who stays, works, lives and visits Hub Feenix
|
||||
can feel completely safe and well. These rules apply to everyone who works, lives
|
||||
and visits in Hub’s inside and outside premises. Both adults and children follow
|
||||
the same rules, and also the guests who are taking part in events and courses.
|
||||
If for example some other rules have been partly agreed for the course space during
|
||||
the course program, participants must anyhow follow this Code of Conduct outside
|
||||
the course space in public areas. The course leader is responsible to take care,
|
||||
that all the participants follow these rules of the house. The rules include also
|
||||
e.g emailing and social media. They are updated according to need.\r\n\r\nAt Hub
|
||||
Feenix, everyone is treated and addressed kindly, respectfully and equally, regardless
|
||||
of gender, color, age, nationality, profession, sexual orientation or social status.
|
||||
\r\n\r\nEveryone respects other people’s personal space and physical- and mental
|
||||
integrity. Any kind of physical interaction always requires the consent of both
|
||||
parties. Course leaders are responsible for ensuring that this rule is followed
|
||||
also within their course program. If you would experience harassment in any situation,
|
||||
even as a part of a course program you’re attending, please contact our staff.
|
||||
We have a special person for these situations.\r\n\r\nEveryone in Hub Feenix’s
|
||||
inside and outside premises and yards commits to behave in such a way, that he/she
|
||||
doesn't cause disturbance or shock to other people in the area. In public spaces
|
||||
everyone is always wearing clothes, and using swimming suite in sauna and on the
|
||||
swimming beach.\r\n\r\nVegetarian eating is complied in the house, and low alcohol
|
||||
consumption in all Hub's premises and outdoor areas. Hub Feenix is a substance
|
||||
free community.\r\n\r\nEveryone in Hub Feenix respects the property of others.
|
||||
Using of the machines, equipment and spaces of the Hub, is always agreed separately,
|
||||
as well as the fee for using them.\r\n\r\nEveryone in Hub Feenix is obliged to
|
||||
consider others and not cause disturbance to anyone, for example by making unnecessary
|
||||
noice. Loud working and other loud noises must be avoided in the night time between
|
||||
22-8 o’clock.\r\nIMAGE"
|
||||
:image_id: 73
|
||||
- :template: section_full_up
|
||||
:index: 6
|
||||
:page_id: 5
|
||||
:updated_at: 2023-07-20 21:12:52.075410727 +03:00
|
||||
:updated_by: hannaholma@gmail.com
|
||||
:id: 83
|
||||
:card_template: ''
|
||||
:options:
|
||||
text_columns: '2'
|
||||
background: light_orange
|
||||
text_color: solid_black
|
||||
margin: none
|
||||
subheader: ''
|
||||
text_align: center
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
item_align: center
|
||||
:header: 'Would you like to join the hub? '
|
||||
:text: "For example right now we are looking for \r\n\r\na cook\r\na car mechanic\r\na
|
||||
marketing person\r\n\r\nHub Feenix is a huge place with lots of different opportunities.
|
||||
If anything on this website resonates with you, do get in touch!"
|
||||
- :template: section_large_image
|
||||
:index: 6
|
||||
:page_id: 1
|
||||
:header: Audio Video Studio
|
||||
:text: "Now we also have an audio studio equipped with editing computer.\r\nThe
|
||||
all round sound-proofing, Rode microfone and Genelec speakers, makes voice recording,
|
||||
eg podcasts or voiceover sound. professional.\r\nWhile the computer with Davinci
|
||||
Resolve (up 4k), terabytes of storage and Rec.709 broadcast standard monitors
|
||||
make video and audio editing a breeze."
|
||||
:options:
|
||||
margin: none
|
||||
order: right
|
||||
text_color: none
|
||||
text_align: center
|
||||
background: light_gray
|
||||
subheader: ''
|
||||
button_link: ''
|
||||
button_text: ''
|
||||
:updated_at: 2023-08-12 22:25:55.186163888 +03:00
|
||||
:updated_by: torsten@villataika.fi
|
||||
:id: 93
|
||||
:image_id: 119
|
||||
- :template: section_spacer
|
||||
:index: 7
|
||||
:page_id: 5
|
||||
:updated_at: 2023-09-16 01:25:17.518341174 +03:00
|
||||
:updated_by: hannaholma@gmail.com
|
||||
:id: 95
|
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The page you were looking for doesn't exist (404)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
.rails-default-error-page {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #B00100 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
.rails-default-error-page h1 {
|
||||
font-size: 100%;
|
||||
color: #730E15;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="rails-default-error-page">
|
||||
<!-- This file lives in public/404.html -->
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>The page you were looking for doesn't exist.</h1>
|
||||
<p>You may have mistyped the address or the page may have moved.</p>
|
||||
</div>
|
||||
<p>If you are the application owner check the logs for more information.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The change you wanted was rejected (422)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
.rails-default-error-page {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #B00100 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
.rails-default-error-page h1 {
|
||||
font-size: 100%;
|
||||
color: #730E15;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="rails-default-error-page">
|
||||
<!-- This file lives in public/422.html -->
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>The change you wanted was rejected.</h1>
|
||||
<p>Maybe you tried to change something you didn't have access to.</p>
|
||||
</div>
|
||||
<p>If you are the application owner check the logs for more information.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>We're sorry, but something went wrong (500)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
.rails-default-error-page {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #B00100 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
.rails-default-error-page h1 {
|
||||
font-size: 100%;
|
||||
color: #730E15;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="rails-default-error-page">
|
||||
<!-- This file lives in public/500.html -->
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>We're sorry, but something went wrong.</h1>
|
||||
</div>
|
||||
<p>If you are the application owner check the logs for more information.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
After Width: | Height: | Size: 842 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "App",
|
||||
"icons": [
|
||||
{
|
||||
"src": "\/android-icon-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1 @@
|
|||
# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
|
|
@ -0,0 +1,5 @@
|
|||
require "test_helper"
|
||||
|
||||
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
||||
driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
require "test_helper"
|
||||
|
||||
class MembersControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
@member = members(:one)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get members_url
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get new_member_url
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create member" do
|
||||
assert_difference("Member.count") do
|
||||
post members_url, params: { member: { name: @member.name, public: @member.public } }
|
||||
end
|
||||
|
||||
assert_redirected_to member_url(Member.last)
|
||||
end
|
||||
|
||||
test "should show member" do
|
||||
get member_url(@member)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get edit_member_url(@member)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update member" do
|
||||
patch member_url(@member), params: { member: { name: @member.name, public: @member.public } }
|
||||
assert_redirected_to member_url(@member)
|
||||
end
|
||||
|
||||
test "should destroy member" do
|
||||
assert_difference("Member.count", -1) do
|
||||
delete member_url(@member)
|
||||
end
|
||||
|
||||
assert_redirected_to members_url
|
||||
end
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
require "test_helper"
|
||||
|
||||
class PicturesControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
@picture = pictures(:one)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get pictures_url
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get new_picture_url
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create picture" do
|
||||
assert_difference("Picture.count") do
|
||||
post pictures_url, params: { picture: { member_id: @picture.member_id, picture: @picture.picture, text: @picture.text } }
|
||||
end
|
||||
|
||||
assert_redirected_to picture_url(Picture.last)
|
||||
end
|
||||
|
||||
test "should show picture" do
|
||||
get picture_url(@picture)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get edit_picture_url(@picture)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update picture" do
|
||||
patch picture_url(@picture), params: { picture: { member_id: @picture.member_id, picture: @picture.picture, text: @picture.text } }
|
||||
assert_redirected_to picture_url(@picture)
|
||||
end
|
||||
|
||||
test "should destroy picture" do
|
||||
assert_difference("Picture.count", -1) do
|
||||
delete picture_url(@picture)
|
||||
end
|
||||
|
||||
assert_redirected_to pictures_url
|
||||
end
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
require "test_helper"
|
||||
|
||||
class StoriesControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
@story = stories(:one)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get stories_url
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get new_story_url
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create story" do
|
||||
assert_difference("Story.count") do
|
||||
post stories_url, params: { story: { happened: @story.happened, header: @story.header, picture: @story.picture, text: @story.text } }
|
||||
end
|
||||
|
||||
assert_redirected_to story_url(Story.last)
|
||||
end
|
||||
|
||||
test "should show story" do
|
||||
get story_url(@story)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get edit_story_url(@story)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update story" do
|
||||
patch story_url(@story), params: { story: { happened: @story.happened, header: @story.header, picture: @story.picture, text: @story.text } }
|
||||
assert_redirected_to story_url(@story)
|
||||
end
|
||||
|
||||
test "should destroy story" do
|
||||
assert_difference("Story.count", -1) do
|
||||
delete story_url(@story)
|
||||
end
|
||||
|
||||
assert_redirected_to stories_url
|
||||
end
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
# one:
|
||||
# record: name_of_fixture (ClassOfFixture)
|
||||
# name: content
|
||||
# body: <p>In a <i>million</i> stars!</p>
|
|
@ -0,0 +1,9 @@
|
|||
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
name: MyString
|
||||
public: false
|
||||
|
||||
two:
|
||||
name: MyString
|
||||
public: false
|
|
@ -0,0 +1,11 @@
|
|||
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
picture: MyString
|
||||
text: MyString
|
||||
member: one
|
||||
|
||||
two:
|
||||
picture: MyString
|
||||
text: MyString
|
||||
member: two
|
|
@ -0,0 +1,13 @@
|
|||
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
picture: MyString
|
||||
header: MyString
|
||||
text: MyText
|
||||
happened: 2023-01-11
|
||||
|
||||
two:
|
||||
picture: MyString
|
||||
header: MyString
|
||||
text: MyText
|
||||
happened: 2023-01-11
|
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class MemberTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class PictureTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class StoryTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
require 'test_helper'
|
||||
|
||||
class PicturePolicyTest < ActiveSupport::TestCase
|
||||
def test_scope
|
||||
end
|
||||
|
||||
def test_show
|
||||
end
|
||||
|
||||
def test_create
|
||||
end
|
||||
|
||||
def test_update
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
require "application_system_test_case"
|
||||
|
||||
class MembersTest < ApplicationSystemTestCase
|
||||
setup do
|
||||
@member = members(:one)
|
||||
end
|
||||
|
||||
test "visiting the index" do
|
||||
visit members_url
|
||||
assert_selector "h1", text: "Members"
|
||||
end
|
||||
|
||||
test "should create member" do
|
||||
visit members_url
|
||||
click_on "New member"
|
||||
|
||||
fill_in "Name", with: @member.name
|
||||
check "Public" if @member.public
|
||||
click_on "Create Member"
|
||||
|
||||
assert_text "Member was successfully created"
|
||||
click_on "Back"
|
||||
end
|
||||
|
||||
test "should update Member" do
|
||||
visit member_url(@member)
|
||||
click_on "Edit this member", match: :first
|
||||
|
||||
fill_in "Name", with: @member.name
|
||||
check "Public" if @member.public
|
||||
click_on "Update Member"
|
||||
|
||||
assert_text "Member was successfully updated"
|
||||
click_on "Back"
|
||||
end
|
||||
|
||||
test "should destroy Member" do
|
||||
visit member_url(@member)
|
||||
click_on "Destroy this member", match: :first
|
||||
|
||||
assert_text "Member was successfully destroyed"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
require "application_system_test_case"
|
||||
|
||||
class PicturesTest < ApplicationSystemTestCase
|
||||
setup do
|
||||
@picture = pictures(:one)
|
||||
end
|
||||
|
||||
test "visiting the index" do
|
||||
visit pictures_url
|
||||
assert_selector "h1", text: "Pictures"
|
||||
end
|
||||
|
||||
test "should create picture" do
|
||||
visit pictures_url
|
||||
click_on "New picture"
|
||||
|
||||
fill_in "Member", with: @picture.member_id
|
||||
fill_in "Picture", with: @picture.picture
|
||||
fill_in "Text", with: @picture.text
|
||||
click_on "Create Picture"
|
||||
|
||||
assert_text "Picture was successfully created"
|
||||
click_on "Back"
|
||||
end
|
||||
|
||||
test "should update Picture" do
|
||||
visit picture_url(@picture)
|
||||
click_on "Edit this picture", match: :first
|
||||
|
||||
fill_in "Member", with: @picture.member_id
|
||||
fill_in "Picture", with: @picture.picture
|
||||
fill_in "Text", with: @picture.text
|
||||
click_on "Update Picture"
|
||||
|
||||
assert_text "Picture was successfully updated"
|
||||
click_on "Back"
|
||||
end
|
||||
|
||||
test "should destroy Picture" do
|
||||
visit picture_url(@picture)
|
||||
click_on "Destroy this picture", match: :first
|
||||
|
||||
assert_text "Picture was successfully destroyed"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
require "application_system_test_case"
|
||||
|
||||
class StoriesTest < ApplicationSystemTestCase
|
||||
setup do
|
||||
@story = stories(:one)
|
||||
end
|
||||
|
||||
test "visiting the index" do
|
||||
visit stories_url
|
||||
assert_selector "h1", text: "Stories"
|
||||
end
|
||||
|
||||
test "should create story" do
|
||||
visit stories_url
|
||||
click_on "New story"
|
||||
|
||||
fill_in "Happened", with: @story.happened
|
||||
fill_in "Header", with: @story.header
|
||||
fill_in "Picture", with: @story.picture
|
||||
fill_in "Text", with: @story.text
|
||||
click_on "Create Story"
|
||||
|
||||
assert_text "Story was successfully created"
|
||||
click_on "Back"
|
||||
end
|
||||
|
||||
test "should update Story" do
|
||||
visit story_url(@story)
|
||||
click_on "Edit this story", match: :first
|
||||
|
||||
fill_in "Happened", with: @story.happened
|
||||
fill_in "Header", with: @story.header
|
||||
fill_in "Picture", with: @story.picture
|
||||
fill_in "Text", with: @story.text
|
||||
click_on "Update Story"
|
||||
|
||||
assert_text "Story was successfully updated"
|
||||
click_on "Back"
|
||||
end
|
||||
|
||||
test "should destroy Story" do
|
||||
visit story_url(@story)
|
||||
click_on "Destroy this story", match: :first
|
||||
|
||||
assert_text "Story was successfully destroyed"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
ENV["RAILS_ENV"] ||= "test"
|
||||
require_relative "../config/environment"
|
||||
require "rails/test_help"
|
||||
|
||||
class ActiveSupport::TestCase
|
||||
# Run tests in parallel with specified workers
|
||||
parallelize(workers: :number_of_processors)
|
||||
|
||||
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
||||
fixtures :all
|
||||
|
||||
# Add more helper methods to be used by all tests here...
|
||||
end
|