diff --git a/app/assets/javascripts/admin/appstack.js b/app/assets/javascripts/admin/appstack.js index aa96e4785e2122a1d5a8f8f4f5c96192ec2041f6..288469caaf16052c44adc410d92efad1a25c718e 100644 --- a/app/assets/javascripts/admin/appstack.js +++ b/app/assets/javascripts/admin/appstack.js @@ -12,6 +12,7 @@ //= require summernote/summernote-bs5 //= require slug/slug //= require cocoon +//= require codemirror/lib/codemirror //= require_self //= require_tree ./commons //= require_tree ../application/plugins diff --git a/app/assets/javascripts/admin/plugins/codemirror.js b/app/assets/javascripts/admin/plugins/codemirror.js new file mode 100644 index 0000000000000000000000000000000000000000..553e9afd748b24c9bf3dee73f9bd49c39d0b5d11 --- /dev/null +++ b/app/assets/javascripts/admin/plugins/codemirror.js @@ -0,0 +1,53 @@ +//= require codemirror/mode/xml/xml +//= require codemirror/mode/javascript/javascript +//= require codemirror/mode/css/css +//= require codemirror/mode/htmlmixed/htmlmixed +//= require codemirror/mode/sass/sass + +/*global CodeMirror */ + +// Add [data-provider="codemirror"] to textarea. +// You need to set [data-codemirror-mode="<language>"] to set the language. +// You can use set [data-codemirror-indentation="n"] to set the indentation level (2 by default). +window.codemirrorManager = { + init: function () { + 'use strict'; + var i; + this.textareas = document.querySelectorAll('textarea[data-provider="codemirror"]'); + this.instances = []; + for (i = 0; i < this.textareas.length; i += 1) { + this.instances.push(this.createInstance(this.textareas[i])); + } + }, + + createInstance: function (textarea) { + 'use strict'; + var mode = textarea.getAttribute('data-codemirror-mode'), + indentationLevel = window.parseInt(textarea.getAttribute('data-codemirror-indentation')); + + if (isNaN(indentationLevel)) { + indentationLevel = 2; + } + + return CodeMirror.fromTextArea(textarea, { + lineNumbers: true, + matchBrackets: true, + styleActiveLine: true, + indentUnit: indentationLevel, + viewportMargin: Infinity, + mode: mode + }); + }, + + invoke: function () { + 'use strict'; + return { + init: this.init.bind(this) + }; + } +}.invoke(); + +window.addEventListener('DOMContentLoaded', function () { + 'use strict'; + window.codemirrorManager.init(); +}); diff --git a/app/assets/javascripts/admin/pure.js b/app/assets/javascripts/admin/pure.js index ce84c279a86652825ff124a99876d8cf2f5339c1..94017fb5f5845850521b0e158949325b6794e6f7 100644 --- a/app/assets/javascripts/admin/pure.js +++ b/app/assets/javascripts/admin/pure.js @@ -13,6 +13,7 @@ //= require summernote/summernote-bs5 //= require slug/slug //= require cocoon +//= require codemirror/lib/codemirror //= require_self //= require_tree ./commons //= require_tree ../application/plugins diff --git a/app/assets/stylesheets/admin/appstack.sass b/app/assets/stylesheets/admin/appstack.sass index 06e674993f421ad82117422b524ea86c91d90846..3413526ba440914d25ccfa8aea3f2e44d45ddf3e 100644 --- a/app/assets/stylesheets/admin/appstack.sass +++ b/app/assets/stylesheets/admin/appstack.sass @@ -7,6 +7,7 @@ @import 'summernote-bs5' @import 'cropperjs/dist/cropper' @import 'gdpr/cookie_consent' +@import 'codemirror/lib/codemirror' @import '../commons/*' @import 'commons/*' @import 'appstack/*' diff --git a/app/assets/stylesheets/admin/commons/codemirror.sass b/app/assets/stylesheets/admin/commons/codemirror.sass new file mode 100644 index 0000000000000000000000000000000000000000..f7c3a66762077a977db4ae333af3814473903be8 --- /dev/null +++ b/app/assets/stylesheets/admin/commons/codemirror.sass @@ -0,0 +1,2 @@ +.CodeMirror + border: 1px solid #CED4DA \ No newline at end of file diff --git a/app/assets/stylesheets/admin/pure.sass b/app/assets/stylesheets/admin/pure.sass index a769401d2472d51dab00ff4d314da975acb0c262..3a2248c6d08bd76b573ece1fce347666a5d0c63a 100644 --- a/app/assets/stylesheets/admin/pure.sass +++ b/app/assets/stylesheets/admin/pure.sass @@ -10,6 +10,7 @@ @import 'summernote-bs5' @import 'cropperjs/dist/cropper' @import 'gdpr/cookie_consent' +@import 'codemirror/lib/codemirror' @import '../commons/*' @import 'commons/*' @import 'pure/buttons' diff --git a/app/controllers/extranet/pages_controller.rb b/app/controllers/extranet/pages_controller.rb index 1cb2242cc14d3f32c33f1aeac241531f59861786..a3bc8035e5d7d9c40a26063051c6c4832affdcb5 100644 --- a/app/controllers/extranet/pages_controller.rb +++ b/app/controllers/extranet/pages_controller.rb @@ -17,14 +17,21 @@ class Extranet::PagesController < Extranet::ApplicationController end def data - @metrics = [ - { value: current_extranet.alumni.count, name: University::Person::Alumnus.model_name.human(count: 2) }, - { value: current_extranet.users.count, name: User.model_name.human(count: 2) }, - { value: current_extranet.experiences.count, name: University::Person::Experience.model_name.human(count: 2) }, - { value: current_extranet.academic_years.count, name: Education::AcademicYear.model_name.human(count: 2) }, - { value: current_extranet.cohorts.count, name: Education::Cohort.model_name.human(count: 2) }, - { value: current_extranet.organizations.count, name: University::Organization.model_name.human(count: 2) }, - ] + @metrics = [] + if current_extranet.has_feature?(:alumni) + @metrics.concat [ + { value: current_extranet.alumni.count, name: University::Person::Alumnus.model_name.human(count: 2) }, + { value: current_extranet.academic_years.count, name: Education::AcademicYear.model_name.human(count: 2) }, + { value: current_extranet.cohorts.count, name: Education::Cohort.model_name.human(count: 2) } + ] + end + if current_extranet.has_feature?(:alumni) || current_extranet.has_feature?(:contacts) + @metrics.concat [ + { value: current_extranet.users.count, name: User.model_name.human(count: 2) }, + { value: current_extranet.experiences.count, name: University::Person::Experience.model_name.human(count: 2) }, + { value: current_extranet.organizations.count, name: University::Organization.model_name.human(count: 2) } + ] + end breadcrumb add_breadcrumb t('extranet.data') end diff --git a/app/controllers/extranet/style_controller.rb b/app/controllers/extranet/style_controller.rb index dea8f4d4b07d08303b30e5c00abfabf28fc330eb..3eb7c8587a2876c04a9be5b355261ab86f509bf7 100644 --- a/app/controllers/extranet/style_controller.rb +++ b/app/controllers/extranet/style_controller.rb @@ -1,5 +1,7 @@ class Extranet::StyleController < Extranet::ApplicationController + skip_before_action :authenticate_user!, :authorize_extranet_access! + def index render body: current_extranet.css, content_type: 'text/css' end -end \ No newline at end of file +end diff --git a/app/models/communication/extranet.rb b/app/models/communication/extranet.rb index faabfae4280d7d6a74fa33af518642da3104aaf4..6f227728cd853220b83e747ab96e673f3f656c62 100644 --- a/app/models/communication/extranet.rb +++ b/app/models/communication/extranet.rb @@ -104,11 +104,19 @@ class Communication::Extranet < ApplicationRecord alias academic_years years def organizations - about&.alumni_organizations + if about.present? && about.respond_to?(:alumni_organizations) + about.alumni_organizations + else + connected_organizations + end end def experiences - about&.alumni_experiences + if about.present? && about.respond_to?(:alumni_experiences) + about.alumni_experiences + else + experiences_through_connections + end end def url diff --git a/app/models/communication/extranet/document.rb b/app/models/communication/extranet/document.rb index 30a353f9f0e1bc72338072f57042b31978c816b4..081f39cbb290caf496bc1cac72d3051b878208c4 100644 --- a/app/models/communication/extranet/document.rb +++ b/app/models/communication/extranet/document.rb @@ -8,24 +8,18 @@ # published_at :datetime # created_at :datetime not null # updated_at :datetime not null -# category_id :uuid indexed # extranet_id :uuid not null, indexed -# kind_id :uuid indexed # university_id :uuid not null, indexed # # Indexes # -# extranet_document_categories (category_id) # index_communication_extranet_documents_on_extranet_id (extranet_id) # index_communication_extranet_documents_on_university_id (university_id) -# index_extranet_document_kinds (kind_id) # # Foreign Keys # # fk_rails_1272fd263c (extranet_id => communication_extranets.id) -# fk_rails_51f7db2f66 (kind_id => communication_extranet_document_kinds.id) # fk_rails_af877a8c0c (university_id => universities.id) -# fk_rails_eb351dc444 (category_id => communication_extranet_document_categories.id) # class Communication::Extranet::Document < ApplicationRecord include Sanitizable diff --git a/app/models/communication/extranet/with_connections.rb b/app/models/communication/extranet/with_connections.rb index 67841e9235ab6d571a83acd50aa0c5dbb50ac225..1325bfcec6c8751760fa94ad125c951a992930e5 100644 --- a/app/models/communication/extranet/with_connections.rb +++ b/app/models/communication/extranet/with_connections.rb @@ -27,4 +27,8 @@ module Communication::Extranet::WithConnections University::Person.where(id: ids) end + def experiences_through_connections + University::Person::Experience.where(person_id: connected_persons, organization_id: connected_organizations) + end + end \ No newline at end of file diff --git a/app/views/admin/communication/blocks/components/_edit.html.erb b/app/views/admin/communication/blocks/components/_edit.html.erb index b2bc336a1db1ad86780cdde67f3b6f1f2e460177..f3c6a8352944be21b27cfb764eca6860d68614e1 100644 --- a/app/views/admin/communication/blocks/components/_edit.html.erb +++ b/app/views/admin/communication/blocks/components/_edit.html.erb @@ -19,6 +19,7 @@ placeholder ||= t "#{i18n_component}.placeholder", default: '' hint ||= t "#{i18n_component}.hint", default: '' none ||= t "#{i18n_component}.none", default: '' summernote_config ||= "mini-list" +codemirror_mode ||= "htmlmixed" partial = "admin/communication/blocks/components/#{component.kind}/edit" local_assigns[:template] = template @@ -31,5 +32,6 @@ local_assigns[:placeholder] = placeholder local_assigns[:hint] = hint local_assigns[:none] ||= t "#{i18n_component}.none", default: '' local_assigns[:summernote_config] ||= summernote_config +local_assigns[:codemirror_mode] ||= codemirror_mode %> <%= render partial, **local_assigns %> diff --git a/app/views/admin/communication/blocks/components/code/_edit.html.erb b/app/views/admin/communication/blocks/components/code/_edit.html.erb index 378a26d41bc751c05ee349f1ddeca7895b1df33d..c21538631ba9c501802a04f93d723a9f2a6c109b 100644 --- a/app/views/admin/communication/blocks/components/code/_edit.html.erb +++ b/app/views/admin/communication/blocks/components/code/_edit.html.erb @@ -4,7 +4,8 @@ <%= label %> </label> <textarea :id="<%= dom_id.html_safe %>" - class="form-control mb-3" + class="form-control mb-3 codemirror-vue" + data-codemirror-mode="<%= codemirror_mode %>" rows="<%= rows %>" v-model="<%= model %>.<%= property %>" placeholder="<%= placeholder %>"></textarea> diff --git a/app/views/admin/communication/blocks/edit.html.erb b/app/views/admin/communication/blocks/edit.html.erb index d57c344baacdba41e8e45f2cabe0122919169d07..e4813e15a33e370cab21e7dfe3c010a6b4dec19a 100644 --- a/app/views/admin/communication/blocks/edit.html.erb +++ b/app/views/admin/communication/blocks/edit.html.erb @@ -71,9 +71,9 @@ this.uploadFile(event.target, files[0], object, key); }, uploadFile(input, file, object, key) { - var size = Math.round(file.size / 1024 / 1024), + var size = Math.round(file.size / 1024 / 1024), sizeLimit = <%= Communication::Block::IMAGE_MAX_SIZE %>, - sizeLimitMo = 0, + sizeLimitMo = 0, controller; if (input.hasAttribute('data-size-limit')) { sizeLimit = input.getAttribute('data-size-limit'); @@ -107,6 +107,13 @@ this.initSummernote($summernoteElements.get(index)); }.bind(this)); }, + handleCodemirrors() { + var $codemirrorElements = $('.codemirror-vue'); + + $codemirrorElements.each(function(index){ + this.initCodemirror($codemirrorElements.get(index)); + }.bind(this)); + }, initSummernote(element) { var config = element.getAttribute('data-summernote-config') || 'default'; $(element).summernote({ @@ -121,10 +128,21 @@ }.bind(this) } }); + }, + initCodemirror(element) { + CodeMirror.fromTextArea(element, { + lineNumbers: true, + styleActiveLine: true, + indentUnit: 2, + viewportMargin: Infinity, + mode: element.getAttribute('data-codemirror-mode') + }); } }, mounted: function() { this.handleSummernotes(); + // Use Timeout to prevent display issues + setTimeout(this.handleCodemirrors.bind(this), 0); } }); diff --git a/app/views/admin/communication/extranets/_form.html.erb b/app/views/admin/communication/extranets/_form.html.erb index eef002e8e81176d5512e22bc0b363c067fc711ec..c286e5734e615db02d6ccd4412b81f6a3e1bc557 100644 --- a/app/views/admin/communication/extranets/_form.html.erb +++ b/app/views/admin/communication/extranets/_form.html.erb @@ -23,7 +23,14 @@ direct_upload: true %> <%= f.input :color, as: :color %> <%= f.input :home_sentence %> - <%= f.input :sass %> + <%= f.input :sass, + input_html: { + data: { + provider: 'codemirror', + "codemirror-mode": "sass", + "codemirror-indentation": 4 + } + } %> <% end %> </div> <div class="col-xl-6"> diff --git a/app/views/admin/university/organizations/static.html.erb b/app/views/admin/university/organizations/static.html.erb index 60054f0d4fbeacd0eb5c737974fdfedd7db117d9..ac035815dde3defe990bba3c4ff006073013dd31 100644 --- a/app/views/admin/university/organizations/static.html.erb +++ b/app/views/admin/university/organizations/static.html.erb @@ -16,8 +16,6 @@ kind: :zipcode, :city, :country, - :latitude, - :longitude, :phone, :email, :twitter, @@ -43,6 +41,9 @@ contact_details: <%= render 'admin/application/static/contact_detail', variable: :mastodon, data: @about.mastodon, kind: ContactDetails::Mastodon %> <%= render 'admin/application/static/contact_detail', variable: :phone, data: @about.phone, kind: ContactDetails::Phone %> <%= render 'admin/application/static/contact_detail', variable: :email, data: @about.email, kind: ContactDetails::Email %> + geolocation: + latitude: <%= @about.latitude %> + longitude: <%= @about.longitude %> <% if @about.logo.attached? %> logo: "<%= @about.logo.blob.id %>" <% end %> diff --git a/app/views/extranet/layouts/devise.html.erb b/app/views/extranet/layouts/devise.html.erb index b8ebe5083ad89910bc9b58d2daccbed966e33421..554c13eca866b3d294a681f8506f3d266933cbce 100644 --- a/app/views/extranet/layouts/devise.html.erb +++ b/app/views/extranet/layouts/devise.html.erb @@ -31,5 +31,6 @@ </main> <%= render 'extranet/gdpr/cookie_consent' %> <%= render 'bugsnag' %> + <%= javascript_include_tag 'extranet' %> </body> </html> diff --git a/db/schema.rb b/db/schema.rb index a22638c875fdcf348e49f48ff14b1b897ccfa479..c3b3ab0a1e1bce6a6dd4c41a447021c8df8a8725 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -214,7 +214,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_131421) do t.index ["communication_website_post_id", "communication_website_category_id"], name: "post_category" end - create_table "communication_website_git_files", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_git_files", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| t.string "previous_path" t.string "about_type", null: false t.uuid "about_id", null: false diff --git a/package.json b/package.json index bea2adeadb53d5f70e63ae09c35ceb6b12cb0879..11690b06ba4a455b22621bafeea7231ffad8c7e0 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "bootstrap-icons": "^1.9.1", "bootstrap-print-css": "^1.0.1", + "codemirror": "5", "cropperjs": "^1.5.12", "jquery-cropper": "^1.0.1", "notyf": "^3.10.0", diff --git a/test/fixtures/communication/extranet/documents.yml b/test/fixtures/communication/extranet/documents.yml index fb4fa23733ee89bef580ed42a2418d63d9d1b4cd..be1d0d6ab57326b590356596a4609a335ddd6e69 100644 --- a/test/fixtures/communication/extranet/documents.yml +++ b/test/fixtures/communication/extranet/documents.yml @@ -8,24 +8,18 @@ # published_at :datetime # created_at :datetime not null # updated_at :datetime not null -# category_id :uuid indexed # extranet_id :uuid not null, indexed -# kind_id :uuid indexed # university_id :uuid not null, indexed # # Indexes # -# extranet_document_categories (category_id) # index_communication_extranet_documents_on_extranet_id (extranet_id) # index_communication_extranet_documents_on_university_id (university_id) -# index_extranet_document_kinds (kind_id) # # Foreign Keys # # fk_rails_1272fd263c (extranet_id => communication_extranets.id) -# fk_rails_51f7db2f66 (kind_id => communication_extranet_document_kinds.id) # fk_rails_af877a8c0c (university_id => universities.id) -# fk_rails_eb351dc444 (category_id => communication_extranet_document_categories.id) # one: diff --git a/yarn.lock b/yarn.lock index a8431a395052b1f0405556a0c582ccce88c64c1d..c7d515077ce9a861f931e17189c3cecd9862a22a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -107,6 +107,11 @@ bootstrap-print-css@^1.0.1: resolved "https://registry.yarnpkg.com/bootstrap-print-css/-/bootstrap-print-css-1.0.1.tgz#acc0264388caebbad0805e60c869d42cd6fe55bf" integrity sha512-I73Cw87BaxCccTjo3qEbvn7KRb55msMxTuT7mpkAAY4Obq8iG9xCybdxnJqq+RrykLD79O3092AiJwaKiEex7w== +codemirror@5: + version "5.65.12" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.12.tgz#294fdf097d10ac5b56a9e011a91eff252afc73ae" + integrity sha512-z2jlHBocElRnPYysN2HAuhXbO3DNB0bcSKmNz3hcWR2Js2Dkhc1bEOxG93Z3DeUrnm+qx56XOY5wQmbP5KY0sw== + cropperjs@^1.5.12: version "1.5.12" resolved "https://registry.yarnpkg.com/cropperjs/-/cropperjs-1.5.12.tgz#d9c0db2bfb8c0d769d51739e8f916bbc44e10f50"