chore: reorganize para current/, rails 8.1, testes e readme

- move app para current/ (estrutura capistrano)
- rails 7.2 → 8.1, ruby 3.2, sqlite3 2.x
- adiciona primary_key Idinformativo no model
- schema.rb completo com todas as tabelas
- testes minitest: models (Tag, Informativo, Tema) e controllers
- readme atualizado em pt-br com stack e instruções de desenvolvimento
- gitignore exclui dump.sql, *.duckdb e sqlite3
This commit is contained in:
2026-06-18 18:58:01 +02:00
parent 691ed8e7e5
commit 25832564f9
132 changed files with 2067 additions and 1253 deletions

View File

@@ -0,0 +1,28 @@
ActiveAdmin.register AdminUser do
permit_params :email, :password, :password_confirmation
index do
selectable_column
id_column
column :email
column :current_sign_in_at
column :sign_in_count
column :created_at
actions
end
filter :email
filter :current_sign_in_at
filter :sign_in_count
filter :created_at
form do |f|
f.inputs do
f.input :email
f.input :password
f.input :password_confirmation
end
f.actions
end
end

View File

@@ -0,0 +1,33 @@
ActiveAdmin.register_page "Dashboard" do
menu false
# menu priority: 1, label: proc { I18n.t("active_admin.dashboard") }
content title: proc { I18n.t("active_admin.dashboard") } do
div class: "blank_slate_container", id: "dashboard_default_message" do
span class: "blank_slate" do
span I18n.t("active_admin.dashboard_welcome.welcome")
small I18n.t("active_admin.dashboard_welcome.call_to_action")
end
end
# Here is an example of a simple dashboard with columns and panels.
#
# columns do
# column do
# panel "Recent Posts" do
# ul do
# Post.recent(5).map do |post|
# li link_to(post.title, admin_post_path(post))
# end
# end
# end
# end
# column do
# panel "Info" do
# para "Welcome to ActiveAdmin."
# end
# end
# end
end # content
end

View File

@@ -0,0 +1,37 @@
ActiveAdmin.register Informativo do
permit_params :Idinformativo, :titulo, :Descricao, :Idtipo, :Abrangencia, :Datainc, :tema1, :subtema1, :tema2, :subtema2, :tema3, :subtema3, :tema4, :subtema4, :operador_inc, :operador_alt, :markdown, tag_ids: []
index do
selectable_column
column :Idinformativo
column :titulo
column :Abrangencia
column :Datainc
column :operador_inc
actions
end
filter :titulo
filter :operador_inc
form do |f|
f.inputs 'Informativo' do
f.input :Datainc, as: :date_time_picker
f.input :titulo
f.input :operador_inc
f.input :tag_ids, as: :tags, collection: Tag.all, display_name: :nome
f.trix_editor :Descricao
end
actions
end
show do
attributes_table do
row :titulo
# row :image do |ad|
# image_tag ad.image.url
# end
end
end
end

18
current/app/admin/tags.rb Normal file
View File

@@ -0,0 +1,18 @@
ActiveAdmin.register Tag do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# Uncomment all parameters which should be permitted for assignment
#
# permit_params :nome, :param, :count
#
# or
#
# permit_params do
# permitted = [:nome, :param, :count]
# permitted << :other if params[:action] == 'create' && current_user.admin?
# permitted
# end
end

View File

@@ -0,0 +1,18 @@
ActiveAdmin.register Tema do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# Uncomment all parameters which should be permitted for assignment
#
# permit_params :reg, :cod_tema, :cod_tema_sub, :tema, :ativo, :padrao, :count, :param
#
# or
#
# permit_params do
# permitted = [:reg, :cod_tema, :cod_tema_sub, :tema, :ativo, :padrao, :count, :param]
# permitted << :other if params[:action] == 'create' && current_user.admin?
# permitted
# end
end

View File

@@ -0,0 +1,3 @@
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,3 @@
//= require trix
//= require active_admin/base
//= require activeadmin_addons/all

View File

@@ -0,0 +1 @@
//= require active_admin/base

View File

@@ -0,0 +1,17 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
// vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery-3.4.0.min
$(document).ready(function(){
console.log("- by http://extrapolo.com -")
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
@import 'activeadmin_addons/all';
// SASS variable overrides must be declared before loading up Active Admin's styles.
//
// To view the variables that Active Admin provides, take a look at
// `app/assets/stylesheets/active_admin/mixins/_variables.scss` in the
// Active Admin source.
//
// For example, to change the sidebar width:
// $sidebar-width: 242px;
// Active Admin's got SASS!
@import "active_admin/mixins";
@import "active_admin/base";
//*= require trix
.trix-button--icon-attach{
display: none
}
// Overriding any non-variable SASS must be done after the fact.
// For example, to change the default status-tag color:
//
// .status_tag { background: #6090DB; }

View File

@@ -0,0 +1,205 @@
p{
margin: 0px;
padding: 0px;
}
@font-face {
font-family: 'wild';
src: url('wildgrowth-webfont.woff2') format('woff2'),
url('wildgrowth-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
body {
padding: 20px;
font-family: 'Fira Sans', monospace;
background-color: #fff;
color: #4c4e4d;
background-image: url(bg.png);
background-repeat: repeat;
background-attachment: fixed;
}
a{
text-decoration: none;
color: #4c4e4d;
}
a:hover {
color:black;
}
#temas{
display: inline-block;
padding-right: 40px;
float: left;
width: 300px
}
.tema{
display: block;
background-color: #12d612d1;
margin: 5px;
padding: 2px;
padding-left: 10px;
padding-right: 10px;
color: black;
font-size: 14px;
padding-top: 4px;
text-decoration: none;
}
.tema:hover{
color: white;
background-color: green;
cursor: pointer;
}
.content{
display: contents;
color: black;
}
.content:hover{
color: white
}
.right{
float: right;
padding-left: 20px;
}
.logo{
font-family: "wild";
font-size: 30px;
padding-left: 50px;
letter-spacing: 3px;
text-shadow: 9px 5px 5px #0061226e;
user-select: none;
font-weight: bold;
}
.logo_img{
width: 215px;
padding: 3px 0px 0px 15px;
}
.texto{
font-size: 14px;
padding: 10px 10px 10px 0px;
background-color: white;
margin-top: 15px;
/* padding: 10px; */
border: 1px solid #80808036;
padding: 15px;
margin-bottom: 15px;
box-shadow: 5px 4px 14px 0px #80808038;
}
.texto>p{
margin-bottom: 10px;
line-height: 18px
}
#busca{
display: inline-block;
float: right;
padding-right: 25px;
padding-top: 12px;
}
.busca-btn{
padding: 3px;
border: 1px;
font-weight: 900;
width: 25px;
color: white;
background-color: #006122;
}
.busca-input{
font-family: 'Fira Sans';
padding: 3px;
border: 1px;
background-color: #33f739b0;
width: 190px;
}
#all{
width: 900px;
margin: 0px auto;
margin-top: 50px;
}
.link{
background-color: #ffdb00;
padding: 4px;
line-height: 33px;
display: inline;
font-weight: bold;
}
.tag{
display: inline-block;
padding: 4px;
margin: 3px;
background-color: #d8d4d4;
font-size: 12px;
}
#tags{
text-align: center;
padding: 10px 0px 25px 0px;
}
#informativos{
display: flow-root;
}
.tags{
margin: 2px;
display: inline-flex;
background-color: #d8d4d4b8;
font-size: 12px;
padding: 2px;
font-weight: normal;
}
h2{
margin: 0px
}
h3{
text-align: right;
font-size:15px;
}
#topo{
background-image: linear-gradient(to right, #47a91c, #066f09);
width: 100%;
display: inline-block;
top: 0px;
left: 0px;
position: absolute;
height: 45px;
border-bottom: 1px solid lightgray
}
.card{
/* color: black; */
width: 100%;
border-top: 1px solid lightgray;
padding-top: 10px;
display: inline-block;
background-color: white;
margin-bottom: 8px
}
.date{
font-size: 12px;
color: gray;
padding-top: 10px;
background-color: white;
display: table;
}
#nav{
display: inline-block;
width: 100%;
text-align: center;
padding: 10px;
font-size: 19px;
background-image: linear-gradient(to right, #33f739 , #329c04);
}
#baixo{
background-color: #d3d3d3bf;
font-size: 11px;
width: 100%;
/* bottom: 0px; */
position: fixed;
bottom: 0px;
left: 0px;
padding: 4px;
text-align: center;
}

View File

@@ -0,0 +1,2 @@
class ApplicationController < ActionController::Base
end

View File

View File

@@ -0,0 +1,41 @@
class PageController < ApplicationController
# caches_page :home, :informativo
def home
@informativos = Informativo.order("Datainc desc").page(params[:page] || 1)
end
def informativo
@informativo = Informativo.find(params[:id])
@title = @informativo.titulo
end
def tag
@tag = Tag.find_by(param: params[:param])
@informativos = @tag.informativos.page(params[:page] || 1)
@title = @tag.nome
render "list"
end
def tema
@tema = Tema.find_by(param: params[:param])
@informativos = @tema.informativos.page(params[:page] || 1)
@title = @tema.padrao
render "list"
end
def busca
@search = params[:q]
terms = @search.to_s.split(/\s+/)
scope = Informativo.all
terms.each do |term|
clean = term.gsub(/[+\-*"()~<>]/, "")
next if clean.blank?
scope = scope.where("titulo LIKE ?", "%#{clean}%")
end
@informativos = scope.order("Datainc desc").page(params[:page] || 1)
@title = "Busca: #{@search}"
render "list"
end
end

View File

@@ -0,0 +1,2 @@
module ApplicationHelper
end

View File

@@ -0,0 +1,10 @@
class AdminUser < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :validatable
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :validatable
end

View File

@@ -0,0 +1,3 @@
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end

View File

View File

@@ -0,0 +1,27 @@
class Informativo < ApplicationRecord
self.table_name = "informativo"
self.primary_key = "Idinformativo"
has_and_belongs_to_many :tags
before_save :meta
def temas
Tema.where("cod_tema = #{self.tema1} or cod_tema = #{self.tema2} or cod_tema = #{self.tema3}").map(&:tema)
end
def as_markdown
html = HTMLPage.new :contents => self.Descricao
html.markdown
end
def to_html
Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(self.markdown)
end
private
def meta
#expire_page action: "show", id: params[:list][:id]
self.Datainc = DateTime.now unless self.Datainc
end
end

16
current/app/models/tag.rb Normal file
View File

@@ -0,0 +1,16 @@
class Tag < ApplicationRecord
has_and_belongs_to_many :informativos
before_save :parameterize
validates :nome, uniqueness: true
def self.top
Tag.limit(80).order("count DESC")
end
private
def parameterize
self.nome.strip!
self.param = self.nome.parameterize
puts "Tag: #{self.nome}"
end
end

View File

@@ -0,0 +1,11 @@
class Tema < ApplicationRecord
self.table_name = "temas"
def self.infos
Tema.where(cod_tema_sub: 0).where.not(padrao: "").map { |t| [t.padrao, t.count] }.sort_by { |_, c| -c }
end
def informativos
Informativo.where("tema1 = ? OR tema2 = ? OR tema3 = ?", cod_tema, cod_tema, cod_tema)
end
end

View File

@@ -0,0 +1,35 @@
!!!
%html
%head
%meta{content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
- title = "Ambiente Já!"
- title = "#{@title} - #{title}" if @title
%title= title
= csrf_meta_tags
= csp_meta_tag
= favicon_link_tag asset_path('favicon.ico')
= stylesheet_link_tag "https://fonts.googleapis.com/css?family=Fira+Sans&display=swap"
= stylesheet_link_tag 'application', media: 'all'
= javascript_include_tag 'application'
%body
#all
#topo
= link_to image_tag("logo.png", class: "logo_img"), "/"
#busca
= form_tag("/search", method: :get) do
= text_field_tag :q, "", class: 'busca-input', placeholder: "+agrofloresta +vida -lixo"
= submit_tag '⌕', class: 'busca-btn'
#temas
- Tema.infos.each do |t|
= link_to "/tema/#{t[0].parameterize}", class: "tema" do
%span.content= t[0]
%span.right= "(#{t[1]})"
= yield :tags
#informativos
= yield
#baixo
%span - AmbienteJá desde 2001 -

View File

@@ -0,0 +1,16 @@
- content_for :tags do
#tags
- Tag.top.each do |t|
%span= link_to "#{t.nome} (#{t.count})", "/tag/#{t.param}", class: "tags", target: "blank"
#informativos
- @informativos.each do |i|
.card
%p= link_to i.titulo.html_safe, CGI.unescapeHTML("/informativo/#{i.id}"), class: "link"
- i.tags.each do |t|
%span= link_to t.nome, "/tag/#{t.param}", class: "tags", target: "blank"
- from = i.operador_inc ? " | #{i.operador_inc.downcase.capitalize}" : ""
.date= "#{i.Datainc} #{from}"
#nav
= will_paginate @informativos

View File

@@ -0,0 +1,25 @@
:javascript
$(document).ready(function(){
$(".texto a").each(function(a){
$(this).attr("target", "_blank");
})
});
#todo
%h2.link= @informativo.titulo.html_safe
#br{style: "padding-top: 4px"}
- @informativo.tags.each do |t|
%span= link_to t.nome, "/tag/#{t.param}", class: "tags", target: "blank"
- from = @informativo.operador_inc ? " | #{@informativo.operador_inc.downcase.capitalize}" : ""
.date= "#{@informativo.Datainc} #{from}"
.texto!= @informativo.Descricao #to_html
-# %hr
-# != ap @informativo
%hr
#tags
- Tag.top.each do |t|
%span= link_to "#{t.nome} (#{t.count})", "/tag/#{t.param}", class: "tags", target: "blank"

View File

@@ -0,0 +1,14 @@
%h2.link= "[ #{@title} ]"
-# .date= "#{@informativos.count} informativos"
#br{style: "padding: 5px 0px 5px"}
- @informativos.each do |i|
.card
%p= link_to i.titulo.html_safe, CGI.unescapeHTML("/informativo/#{i.id}"), class: "link"
- i.tags.each do |t|
%span= link_to t.nome, "/tag/#{t.param}", class: "tags", target: "blank"
- from = i.operador_inc ? " | #{i.operador_inc.downcase.capitalize}" : ""
.date= "#{i.Datainc} #{from}"
#nav
= will_paginate @informativos