added dictionary feature
This commit is contained in:
parent
a86b2b8995
commit
abbb95ecb7
|
|
@ -15,11 +15,11 @@
|
|||
//= require turbolinks
|
||||
function reloadFunctionsOnAjax() {
|
||||
$(".tooltip").tooltip("hide");
|
||||
//$('.popover').popover('hide');
|
||||
$('.popover').popover('hide');
|
||||
|
||||
// Reload tootltips
|
||||
$('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' })
|
||||
|
||||
// Reload popovers
|
||||
//$('[data-toggle="popover"]').popover()
|
||||
$('[data-toggle="popover"]').popover()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,3 +109,9 @@
|
|||
.text-navy-new:hover {
|
||||
color: #0a3a7e;
|
||||
}
|
||||
|
||||
.dictionary-word {
|
||||
text-decoration: underline;
|
||||
-webkit-text-decoration-color: blue; /* Safari */
|
||||
text-decoration-color: blue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Dictionary class
|
||||
class DictionariesController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
include ApplicationHelper
|
||||
before_action :check_access
|
||||
before_action :set_dictionary, only: %i[show edit update destroy]
|
||||
|
||||
def check_access
|
||||
redirect_to not_found unless role?('dictionaries')
|
||||
end
|
||||
|
||||
# GET /tags or /tags.json
|
||||
def index
|
||||
@dictionaries = Dictionary.all
|
||||
end
|
||||
|
||||
# GET /tags/1 or /tags/1.json
|
||||
def show; end
|
||||
|
||||
# GET /tags/new
|
||||
def new
|
||||
@dictionary = Dictionary.new
|
||||
end
|
||||
|
||||
# GET /tags/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST /tags or /tags.json
|
||||
def create
|
||||
@dictionary = Dictionary.new(dictionary_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @dictionary.save
|
||||
format.html { redirect_to dictionaries_url, notice: 'Utworzono pomyślnie.' }
|
||||
format.json { render :show, status: :created, location: @dictionary }
|
||||
else
|
||||
format.html { render :new, status: :unprocessable_entity }
|
||||
format.json { render json: @dictionary.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @dictionary.update(dictionary_params)
|
||||
format.html { redirect_to dictionaries_url, notice: 'Zaktualizowano pomyślnie.' }
|
||||
format.json { render :show, status: :ok, location: @dictionary }
|
||||
else
|
||||
format.html { render :edit, status: :unprocessable_entity }
|
||||
format.json { render json: @dictionary.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@dictionary.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to dictionaries_url, notice: 'Usunięto pomyślnie.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_dictionary
|
||||
@dictionary = Dictionary.find(params[:id])
|
||||
end
|
||||
|
||||
# Only allow a list of trusted parameters through.
|
||||
def dictionary_params
|
||||
params.require(:dictionary).permit(:shortcut, :name, :description)
|
||||
end
|
||||
end
|
||||
|
|
@ -13,6 +13,7 @@ module ApplicationHelper
|
|||
ret += menu_item('far fa-circle', 'Przedsięwzięcia', '/projects', 'projects') if role?('projects')
|
||||
ret += menu_item('far fa-circle', 'Eksperci', '/experts', 'experts') if role?('experts')
|
||||
ret += menu_item('far fa-circle', 'Partnerzy', '/partners', 'partners') if role?('partners')
|
||||
ret += menu_item('far fa-circle', 'Słownik', '/dictionaries', 'dictionaries') if role?('dictionaries')
|
||||
ret += menu_item('far fa-user', 'Użytkownicy', '/settings/users', 'users') if admin?
|
||||
|
||||
ret
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Model Dictionary
|
||||
class Dictionary < ApplicationRecord
|
||||
# == Constants ============================================================
|
||||
|
||||
# == Attributes ===========================================================
|
||||
|
||||
# == Extensions ===========================================================
|
||||
|
||||
# == Relationships ========================================================
|
||||
|
||||
# == Validations ==========================================================
|
||||
validates :name, presence: true, length: { maximum: 255 }
|
||||
validates :shortcut, presence: true, length: { maximum: 50 }
|
||||
validates :description, presence: true, length: { maximum: 1000 }
|
||||
# == Scopes ===============================================================
|
||||
scope :by_short, ->(val) { where(shortcut: val) }
|
||||
# == Callbacks ============================================================
|
||||
|
||||
# == Class Methods ========================================================
|
||||
def self.ret_all_to_tinymce
|
||||
ret = ''
|
||||
Dictionary.all.each do |dict|
|
||||
ret += dict.ret_a_tinymce_element
|
||||
end
|
||||
ret.chomp
|
||||
end
|
||||
|
||||
# == Instance Methods =====================================================
|
||||
def ret_a_tag
|
||||
"<a tabindex='0' data-toggle='popover' data-trigger='hover' title='#{name}"\
|
||||
"' data-content='#{description}' class='dictionary-word'>#{name}</a>"
|
||||
end
|
||||
|
||||
def ret_a_tinymce_element
|
||||
"{type: 'menuitem',text: '#{name}',onAction: function ()"\
|
||||
" {editor.insertContent(' #{shortcut}');}},"
|
||||
end
|
||||
end
|
||||
|
|
@ -152,6 +152,19 @@ class Dotation < ApplicationRecord
|
|||
friendly_id
|
||||
end
|
||||
|
||||
def replace_dictionary(text, form)
|
||||
ret = text
|
||||
dictionaries = Dictionary.all
|
||||
dictionaries.each do |dictionary|
|
||||
if form == 'pdf'
|
||||
ret = ret.gsub(dictionary.shortcut, dictionary.name)
|
||||
elsif form == 'html'
|
||||
ret = ret.gsub(dictionary.shortcut, dictionary.ret_a_tag)
|
||||
end
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def replace_video
|
||||
require 'nokogiri'
|
||||
ret = full_descr
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<%= form_with(model: dictionary, local: true) do |form| %>
|
||||
<%= render '/shared/errors_list', error_object: dictionary %>
|
||||
<div class="form-group">
|
||||
<%= form.label :shortcut %>
|
||||
<%= form.text_field :shortcut, class: 'form-control', placeholder: 'Wprowadź skrót' %>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<%= form.label :name %>
|
||||
<%= form.text_field :name, class: 'form-control', placeholder: 'Wprowadź nazwę' %>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<%= form.label :description %>
|
||||
<%= form.text_area :description, class: 'form-control', placeholder: 'Wprowadź opis' %>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<%= link_to '< Wróć', dictionaries_path, class: 'btn btn-info' %>
|
||||
<button type="submit" class="btn btn-primary">Zapisz</button>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<% if @dictionaries.blank? %>
|
||||
<div class="alert alert-info alert-dismissible">
|
||||
<h5><i class="icon fas fa-info"></i> Informacja</h5>
|
||||
Brak elementów na liście
|
||||
</div>
|
||||
<% else %>
|
||||
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nazwa</th>
|
||||
<th>Opis</th>
|
||||
<th style="width: 200px">Akcje</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<% @dictionaries.each do |dictionary| %>
|
||||
<tr>
|
||||
<td><%= dictionary.name %></td>
|
||||
<td><%= dictionary.description %></td>
|
||||
<td>
|
||||
<%= link_to raw('<i class="fas fa-edit"></i> Edycja'), edit_dictionary_path(dictionary), class: 'btn-sm btn-info' %>
|
||||
<%= link_to raw('<i class="fas fa-trash-can"></i> Usuń'), dictionary, class: 'btn-sm btn-danger', method: :delete, data: { confirm: 'Czy na pewno?' } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<% end %>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0">Słownik</h1>
|
||||
</div>
|
||||
<div class="col-sm-6"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-edit"></i> Edycja pojęcia</h3>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<p id="notice"><%= notice %></p>
|
||||
<%= render 'form', dictionary: @dictionary %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0">Słownik pojęć</h1>
|
||||
</div>
|
||||
<div class="col-sm-6"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-folder"></i> Słownik pojęć</h3>
|
||||
<div class="card-tools">
|
||||
<%= link_to raw('<button type="button" class="btn-sm btn-block btn-primary">Dodaj</button>'), new_dictionary_path %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<p id="notice"><%= notice %></p>
|
||||
<%= render partial: 'list' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0">Słownik</h1>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-sm-6"></div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
</div>
|
||||
<!-- /.container-fluid -->
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-edit"></i> Nowe pojęcie</h3>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<p id="notice"><%= notice %></p>
|
||||
<%= render 'form', dictionary: @dictionary %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -264,7 +264,7 @@
|
|||
'insertdatetime', 'media', 'table', 'code', 'wordcount'
|
||||
],
|
||||
toolbar: 'undo redo | blocks | ' +
|
||||
'bold italic backcolor | alignleft aligncenter ' +
|
||||
'bold italic backcolor | customDictionary | alignleft aligncenter ' +
|
||||
'alignright alignjustify | bullist numlist outdent indent | ' +
|
||||
'removeformat link image media | table tableinsertdialog tablecellprops tableprops advtablerownumbering',
|
||||
/* enable title field in the Image dialog*/
|
||||
|
|
@ -276,6 +276,17 @@
|
|||
images_upload_url: 'postAcceptor.php',
|
||||
here we add custom filepicker only to Image dialog
|
||||
*/
|
||||
setup: function (editor) {
|
||||
editor.ui.registry.addMenuButton('customDictionary', {
|
||||
icon: 'user',
|
||||
tooltip: 'Pojęcie słownikowe',
|
||||
fetch: function (callback) {
|
||||
var items = [<%= raw Dictionary.ret_all_to_tinymce %>];
|
||||
callback(items);
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
file_picker_types: 'image',
|
||||
/* and here's our custom image picker*/
|
||||
file_picker_callback: (cb, value, meta) => {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
<%= render 'activate', dotation: dotation %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to raw('<i class="fas fa-eye"></i> Pokaż'), edit_grant_path(dotation), class: 'btn-sm btn-info' %>
|
||||
<%= link_to raw('<i class="fas fa-eye"></i> Pokaż'), grant_path(dotation), class: 'btn-sm btn-info' %>
|
||||
<%= link_to raw('<i class="fas fa-trash-can"></i> Usuń'), grant_path(dotation), class: 'btn-sm btn-danger', method: :delete, data: { confirm: 'Czy na pewno?' } %>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<%= raw @dotation.full_descr %>
|
||||
<%= raw @dotation.replace_dictionary(@dotation.full_descr, 'html') %>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
<h3 style='text-transform: uppercase;'><b>Szczegółowy opis dotacji</b></h3>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<%= raw @dotation.full_descr %>
|
||||
<%= raw @dotation.replace_dictionary(@dotation.full_descr, 'html') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
<h3 style='text-transform: uppercase;'><b>Szczegółowy opis dotacji</b></h3>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<%= raw dotation.replace_video %>
|
||||
<%= raw dotation.replace_dictionary(dotation.replace_video, 'pdf') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -107,5 +107,8 @@
|
|||
<script type="text/javascript">
|
||||
<%= yield :foot_scripts %>
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
reloadFunctionsOnAjax();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
pl:
|
||||
activerecord:
|
||||
models:
|
||||
tag: Słownik
|
||||
attributes:
|
||||
dictionary:
|
||||
name: "Nazwa"
|
||||
description: "Opis"
|
||||
shortcut: "Skrót"
|
||||
errors:
|
||||
models:
|
||||
dictionary:
|
||||
attributes:
|
||||
name:
|
||||
blank: nie może być pusta
|
||||
too_long: jest za długa (max 255 znaków)
|
||||
description:
|
||||
blank: nie może być pusty
|
||||
too_long: jest za długi (max 1000 znaków)
|
||||
shortcut:
|
||||
blank: nie może być pusty
|
||||
too_long: jest za długi (max 50 znaków)
|
||||
|
|
@ -24,6 +24,7 @@ Rails.application.routes.draw do
|
|||
resources :projects
|
||||
resources :partners
|
||||
resources :experts
|
||||
resources :dictionaries
|
||||
get 'grants/activate'
|
||||
post 'grants/activate'
|
||||
resources :grants
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
class CreateDictionaries < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :dictionaries do |t|
|
||||
t.string :shortcut
|
||||
t.string :name
|
||||
t.longtext :description
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
10
db/schema.rb
10
db/schema.rb
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2022_06_28_085754) do
|
||||
ActiveRecord::Schema.define(version: 2022_06_29_060749) do
|
||||
|
||||
create_table "active_storage_attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
|
|
@ -83,6 +83,14 @@ ActiveRecord::Schema.define(version: 2022_06_28_085754) do
|
|||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "dictionaries", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
|
||||
t.string "shortcut"
|
||||
t.string "name"
|
||||
t.text "description", limit: 4294967295
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "dotations", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
|
||||
t.string "slug"
|
||||
t.string "name"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
shortcut: MyString
|
||||
name: MyString
|
||||
description:
|
||||
|
||||
two:
|
||||
shortcut: MyString
|
||||
name: MyString
|
||||
description:
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
require 'test_helper'
|
||||
|
||||
class DictionaryTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
||||
Loading…
Reference in New Issue