diff --git a/app/assets/images/arrow-right.svg b/app/assets/images/arrow-right.svg
index 21ce5092c3..07eb88ef14 100644
--- a/app/assets/images/arrow-right.svg
+++ b/app/assets/images/arrow-right.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
diff --git a/app/assets/images/success.svg b/app/assets/images/success.svg
new file mode 100644
index 0000000000..1a6d1a81e3
--- /dev/null
+++ b/app/assets/images/success.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/app/assets/images/warning.svg b/app/assets/images/warning.svg
new file mode 100644
index 0000000000..0ca8db2606
--- /dev/null
+++ b/app/assets/images/warning.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/app/assets/images/white-check.svg b/app/assets/images/white-check.svg
new file mode 100644
index 0000000000..6b657da4fd
--- /dev/null
+++ b/app/assets/images/white-check.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/app/assets/images/x.svg b/app/assets/images/x.svg
new file mode 100644
index 0000000000..6be564a080
--- /dev/null
+++ b/app/assets/images/x.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/app/assets/stylesheets/application.css.scss.erb b/app/assets/stylesheets/application.css.scss.erb
index 0810149530..ae2bcd71f6 100755
--- a/app/assets/stylesheets/application.css.scss.erb
+++ b/app/assets/stylesheets/application.css.scss.erb
@@ -51,8 +51,8 @@
@import "components/index";
@import "account";
@import "agents";
+@import "upload_ontology";
@import "edit-ontology";
-
@import "nav_bar";
@import "ontology_details_header";
@import "ontology_viewer";
diff --git a/app/assets/stylesheets/bioportal.scss b/app/assets/stylesheets/bioportal.scss
index 607d236309..c3ccdf04f0 100644
--- a/app/assets/stylesheets/bioportal.scss
+++ b/app/assets/stylesheets/bioportal.scss
@@ -1143,6 +1143,9 @@ a.truncated_less, a.truncated_more {
.highlighted .search_ontology_acronym {
color: white;
}
+.hide {
+ display: none !important;
+}
.empty-state {
display: none;
diff --git a/app/assets/stylesheets/components/alert.scss b/app/assets/stylesheets/components/alert.scss
new file mode 100644
index 0000000000..e68adc4862
--- /dev/null
+++ b/app/assets/stylesheets/components/alert.scss
@@ -0,0 +1,84 @@
+.alert-container{
+ display: flex;
+ align-items: center;
+ padding: 20px;
+ border-radius: 5px;
+}
+.alert-container.alert-info-type{
+ background-color: rgba(59, 130, 246, 0.1);
+}
+.alert-container.alert-warning-type {
+ background-color: rgba(234, 179, 8, 0.1);
+}
+.alert-container.alert-danger-type {
+ background-color: rgba(239, 68, 68, 0.1);
+}
+.alert-container.alert-success-type {
+ background-color: rgba(34, 197, 94, 0.1);
+}
+
+
+
+
+
+.alert-message{
+ font-size: 16px;
+ margin: 0 10px;
+ text-align: center;
+}
+
+
+
+.alert-message.alert-info-type{
+ color: rgb(59, 130, 246);
+}
+.alert-message.alert-warning-type {
+ color: rgb(234, 179, 8);
+}
+.alert-message.alert-danger-type {
+ color: rgb(239, 68, 68);
+}
+.alert-message.alert-success-type {
+ color: rgb(34, 197, 94);
+}
+
+
+
+
+.alert-icon svg{
+ width: 25px;
+ margin: 0 !important;
+}
+.alert-icon.alert-info-type svg path{
+ fill: rgb(59, 130, 246);
+}
+.alert-icon.alert-warning-type svg path {
+ fill: rgb(234, 179, 8);
+}
+.alert-icon.alert-danger-type svg path {
+ fill: rgb(239, 68, 68);
+}
+.alert-icon.alert-success-type svg path {
+ fill: rgb(34, 197, 94);
+}
+
+
+.alert-close svg{
+ width: 25px;
+ cursor: pointer;
+}
+
+.alert-close.alert-info-type svg path{
+ fill:rgb(59, 130, 246);
+}
+.alert-close.alert-warning-type svg path {
+ fill: rgb(234, 179, 8);
+}
+.alert-close.alert-danger-type svg path {
+ fill: rgb(239, 68, 68);
+}
+.alert-close.alert-success-type svg path {
+ fill: rgb(34, 197, 94);
+}
+
+
diff --git a/app/assets/stylesheets/components/chips.scss b/app/assets/stylesheets/components/chips.scss
index d0539b6a0e..9815dbdf1f 100644
--- a/app/assets/stylesheets/components/chips.scss
+++ b/app/assets/stylesheets/components/chips.scss
@@ -1,3 +1,7 @@
+.chips-container > div{
+ margin-right: 10px;
+}
+
.chips-container svg path{
fill: var(--primary-color);
}
@@ -7,6 +11,7 @@
display: none;
}
+
.chips-container div label{
cursor: pointer;
}
@@ -20,9 +25,9 @@
background:white;
border: 0.5px solid #BDBDBD;
color: #a7a7a7;
- padding: 3px;
+ padding: 8px;
border-radius: 5px;
- font-size: 12px;
+ font-size: 13px;
user-select: none;
}
diff --git a/app/assets/stylesheets/components/index.scss b/app/assets/stylesheets/components/index.scss
index 8c061af437..1f6528910a 100644
--- a/app/assets/stylesheets/components/index.scss
+++ b/app/assets/stylesheets/components/index.scss
@@ -24,5 +24,5 @@
@import "card";
@import "header";
@import "image";
-
-
+@import "alert";
+@import "progress_pages";
diff --git a/app/assets/stylesheets/components/input_field.scss b/app/assets/stylesheets/components/input_field.scss
index 9a5ad99c94..f11b84188f 100644
--- a/app/assets/stylesheets/components/input_field.scss
+++ b/app/assets/stylesheets/components/input_field.scss
@@ -66,4 +66,20 @@
right: calc(0.75rem + 5px);
top: 50%;
width: 0;
+}
+
+.ts-wrapper.multi .ts-control>div{
+ border-radius: 5px;
+ font-size: 11px;
+ padding: 2px 0 4px 6px;
+ color: #888888;
+}
+
+.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove{
+ border-left: none;
+ color: #888888 !important;
+ margin-left: 0;
+}
+.ts-wrapper.plugin-remove_button .item .remove:hover{
+ background: unset;
}
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/primary_button.scss b/app/assets/stylesheets/components/primary_button.scss
new file mode 100644
index 0000000000..5e534fecdb
--- /dev/null
+++ b/app/assets/stylesheets/components/primary_button.scss
@@ -0,0 +1,101 @@
+.button-container{
+ width: 100%;
+}
+.primary-button {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 16px;
+ color: white;
+ height: 60px;
+ background-color: var(--primary-color);
+ border: none;
+ border-radius: 9px;
+ transition: background-color ease 0.3s;
+}
+.primary-button:hover {
+ background-color: var(--hover-color);
+ cursor: pointer;
+}
+
+
+.animation-container{
+ width: 100%;
+ height: 60px;
+ font-size: 16px;
+ background-color: var(--hover-color);
+ border: none;
+ border-radius: 9px;
+ justify-content: center;
+ align-items: center;
+ display: none;
+
+}
+.lds-ellipsis {
+ display: inline-block;
+ position: relative;
+ margin-top: 50px;
+ width: 80px;
+ height: 80px;
+ transform: scale(0.7);
+}
+
+.lds-ellipsis div {
+ position: absolute;
+ width: 13px;
+ height: 13px;
+ border-radius: 50%;
+ background: white;
+ animation-timing-function: cubic-bezier(0, 1, 1, 0);
+}
+
+.lds-ellipsis div:nth-child(1) {
+ left: 8px;
+ animation: lds-ellipsis1 0.6s infinite;
+}
+
+.lds-ellipsis div:nth-child(2) {
+ left: 8px;
+ animation: lds-ellipsis2 0.6s infinite;
+}
+
+.lds-ellipsis div:nth-child(3) {
+ left: 32px;
+ animation: lds-ellipsis2 0.6s infinite;
+}
+
+.lds-ellipsis div:nth-child(4) {
+ left: 56px;
+ animation: lds-ellipsis3 0.6s infinite;
+}
+
+@keyframes lds-ellipsis1 {
+ 0% {
+ transform: scale(0);
+ }
+
+ 100% {
+ transform: scale(1);
+ }
+}
+
+@keyframes lds-ellipsis3 {
+ 0% {
+ transform: scale(1);
+ }
+
+ 100% {
+ transform: scale(0);
+ }
+}
+
+@keyframes lds-ellipsis2 {
+ 0% {
+ transform: translate(0, 0);
+ }
+
+ 100% {
+ transform: translate(24px, 0);
+ }
+}
diff --git a/app/assets/stylesheets/components/progress_pages.scss b/app/assets/stylesheets/components/progress_pages.scss
new file mode 100644
index 0000000000..6e3f6cff5c
--- /dev/null
+++ b/app/assets/stylesheets/components/progress_pages.scss
@@ -0,0 +1,118 @@
+.progress-pages-container {
+ display: flex;
+ align-items: center;
+ margin-top: 20px;
+ margin-bottom: 50px;
+ width: 100%;
+}
+
+.progress-pages-container hr {
+ flex-grow: 1;
+ border: 1px solid #D9D9D9;
+ margin: 0;
+}
+
+.progress-pages-container hr.active {
+ border: 1px solid var(--primary-color);
+}
+
+.progress-pages-container .progress-item {
+ position: relative;
+ & > div {
+ position: absolute;
+ top: -13px;
+ left: -13px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+}
+
+.progress-pages-container .progress-item:first-of-type {
+ & > div {
+ align-items: start;
+ left: 0;
+ }
+}
+
+.progress-pages-container .progress-item:last-of-type {
+ & > div {
+ align-items: end;
+ left: -23px;
+ }
+}
+
+.progress-pages-container .progress-item div .active:nth-child(2) {
+ color: var(--primary-color);
+ font-weight: 600;
+}
+
+.progress-pages-container .progress-item div span:nth-child(2) {
+ position: absolute;
+ font-size: 12px;
+ top: 33px;
+ white-space: nowrap;
+ color: #A9A9A9;
+}
+
+.progress-pages-container .progress-content .active:nth-child(2) {
+ color: var(--primary-color);
+ font-weight: 600;
+}
+
+.progress-pages-container .progress-content div:nth-child(2) {
+ position: absolute;
+ right: -38px;
+ top: 33px;
+
+}
+
+
+
+.outlined-checked-circle {
+ border: 2px solid var(--primary-color) !important;
+ background-color: var(--primary-color) !important;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.outlined-active-circle {
+ border: 2px solid var(--primary-color) !important;
+}
+
+.outlined-circle {
+ border: 1px solid #D9D9D9;
+ border-radius: 13px;
+ height: 26px;
+ width: 26px;
+ background-color: white;
+
+}
+
+.outlined-checked-circle img {
+ display: block !important;
+}
+
+.outlined-active-circle img {
+ display: none;
+}
+
+.outlined-circle img {
+ display: none;
+}
+
+
+
+.progress-pages-actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 20px;
+}
+
+.progress-pages-next-button {
+ margin-left: 25px;
+}
+
+
+
diff --git a/app/assets/stylesheets/components/regular_button.scss b/app/assets/stylesheets/components/regular_button.scss
index 9541652970..762b285b28 100644
--- a/app/assets/stylesheets/components/regular_button.scss
+++ b/app/assets/stylesheets/components/regular_button.scss
@@ -105,10 +105,12 @@
.left-button-icon{
margin-right: 10px;
+ margin-bottom: 3px;
}
.right-button-icon {
margin-left: 10px;
+ margin-bottom: 3px;
}
.secondary-button-icon path {
diff --git a/app/assets/stylesheets/upload_ontology.scss b/app/assets/stylesheets/upload_ontology.scss
new file mode 100644
index 0000000000..d5026556ca
--- /dev/null
+++ b/app/assets/stylesheets/upload_ontology.scss
@@ -0,0 +1,105 @@
+.upload-ontology-container {
+ display: flex;
+ justify-content: center;
+ padding: 40px 0;
+}
+
+.upload-ontology-card {
+ width: 589px;
+ border-radius: 14px;
+ box-shadow: rgba(0, 0, 0, 0.05) 0px 20px 50px;
+ padding: 20px 40px;
+
+}
+
+.upload-ontology-center {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+}
+
+.Upload-ontology-title {
+ font-size: 18px;
+ display: flex;
+ font-weight: bold;
+ flex-direction: column;
+ align-items: center;
+}
+
+.Upload-ontology-title hr {
+ border: 1px solid var(--primary-color);
+ width: 93px;
+ margin: 0;
+}
+
+.upload-ontology-progress {
+ display: flex;
+ align-items: center;
+ margin-top: 20px;
+ margin-bottom: 50px;
+}
+
+
+.upload-ontology-chips-container{
+ display: flex;
+ flex-wrap: wrap;
+}
+
+
+.hide {
+ display: none;
+}
+
+.show {
+ display: block;
+}
+
+.upload-ontology-desc {
+ font-size: 12px;
+ color: #777777;
+ margin-bottom: 23px;
+}
+
+.upload-ontology-desc a {
+ text-decoration: none;
+ color: var(--primary-color);
+}
+.upload-ontology-desc a svg{
+ transform: scale(1.2);
+}
+
+
+.upload-ontology-contact .add-another-contact div {
+ font-size: 11px;
+ color: #DADADA;
+ margin-left: 10px;
+
+}
+
+.upload-ontology-field-container .location-choice{
+ display: flex;
+ align-items: center;
+ margin-bottom: 3px;
+}
+
+.upload-ontology-field-container .location-choice .title{
+ font-size: 13px;
+ color: black;
+ margin-left: 13px;
+ margin-bottom: 0;
+ cursor: pointer;
+}
+
+.upload-ontology-field-container > div{
+ font-size: 12px;
+ color: #666666;
+}
+
+
+.upload-ontology-input-field-container{
+ margin-bottom: 10px;
+}
+
+.upload-ontology-input-field-container .switch-filter p{
+ font-size: 12px !important;
+}
diff --git a/app/components/alert_message_component.rb b/app/components/alert_message_component.rb
deleted file mode 100644
index 09ece182b6..0000000000
--- a/app/components/alert_message_component.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AlertMessageComponent < ViewComponent::Base
- include Turbo::FramesHelper
- def initialize(id: '', message: nil, type: 'info', closeable: true)
- @id = id
- @message = message
- @type = "alert-#{type}"
- @closeable = closeable
- end
-end
diff --git a/app/components/alert_message_component/alert_message_component.html.haml b/app/components/alert_message_component/alert_message_component.html.haml
deleted file mode 100644
index c32ec7d3c7..0000000000
--- a/app/components/alert_message_component/alert_message_component.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-.alert.alert-dismissible.fade.show{:role => "alert", class: "#{@type}", style: "text-align: left;white-space: normal;"}
- = @message || content
-
- - if @closeable
- %button.close{"aria-label": "Close", "data-dismiss": "alert", type: "button", style: "background: transparent"}
- %span{"aria-hidden" => "true"} ×
-
-
\ No newline at end of file
diff --git a/app/components/buttons/primary_button_component/primary_button_component.html.haml b/app/components/buttons/primary_button_component/primary_button_component.html.haml
new file mode 100644
index 0000000000..154eb2abe3
--- /dev/null
+++ b/app/components/buttons/primary_button_component/primary_button_component.html.haml
@@ -0,0 +1,23 @@
+- if @type == "submit"
+ .button-container{onclick: "displayAnimation()", id: "primary-button"}
+ %input.primary-button{:name => @name, :type => "submit", :value => @value, oncklick: @onclick}/
+- else
+ .button-container
+ .primary-button{:name => @name, onclick: "displayAnimation()", id: "primary-button", oncklick: @onclick}
+ = @value
+
+.animation-container#loading-animation
+ .lds-ellipsis
+ %div
+ %div
+ %div
+ %div
+
+:javascript
+ const button = document.getElementById("primary-button")
+ const loading = document.getElementById("loading-animation")
+ function displayAnimation(){
+ console.log("working")
+ button.style.display = 'none';
+ loading.style.display = 'flex';
+ }
\ No newline at end of file
diff --git a/app/components/buttons/regular_button_component.rb b/app/components/buttons/regular_button_component.rb
index c40a9f67b0..cb75ef32a3 100644
--- a/app/components/buttons/regular_button_component.rb
+++ b/app/components/buttons/regular_button_component.rb
@@ -16,7 +16,7 @@ def initialize(id: , value:, variant: "primary", color: "normal", href: "", size
def button_label
hide_icon_left = icon_left == nil ? "hide" : " "
hide_icon_right = icon_right == nil ? "hide" : " "
- content_tag(:span, icon_left, class: "#{@variant}-button-icon left-button-icon #{hide_icon_left}") + @value + content_tag(:span, icon_right, class: "#{@variant}-button-icon right-button-icon #{hide_icon_right}")
+ content_tag(:span, icon_left, class: "#{@variant}-button-icon left-button-icon #{hide_icon_left}") + content_tag(:div, @value) + content_tag(:span, icon_right, class: "#{@variant}-button-icon right-button-icon #{hide_icon_right}")
end
def button_elem
diff --git a/app/components/chips_component/chips_component.html.haml b/app/components/chips_component/chips_component.html.haml
index 48a0b88a4e..3191dc1d3b 100644
--- a/app/components/chips_component/chips_component.html.haml
+++ b/app/components/chips_component/chips_component.html.haml
@@ -5,6 +5,6 @@
%span
%svg.chips-check-icon{:fill => "none", :height => "8", :viewbox => "0 0 10 8", :width => "10", :xmlns => "http://www.w3.org/2000/svg"}
%path{:d => "M9.76764 0.232287C9.45824 -0.0775267 8.95582 -0.0773313 8.646 0.232287L3.59787 5.28062L1.35419 3.03696C1.04438 2.72714 0.542174 2.72714 0.23236 3.03696C-0.0774534 3.34677 -0.0774534 3.84897 0.23236 4.15879L3.03684 6.96326C3.19165 7.11807 3.39464 7.19567 3.59765 7.19567C3.80067 7.19567 4.00386 7.11827 4.15867 6.96326L9.76764 1.3541C10.0775 1.0445 10.0775 0.542081 9.76764 0.232287Z"}
- %div.ml-1
+ %div
= @label
= count
diff --git a/app/components/display/alert_component.rb b/app/components/display/alert_component.rb
new file mode 100644
index 0000000000..c381f2a37e
--- /dev/null
+++ b/app/components/display/alert_component.rb
@@ -0,0 +1,47 @@
+class Display::AlertComponent < ViewComponent::Base
+ def initialize(message: nil, closable: true, type: "info", auto_close_delay: nil)
+ @message = message
+ @closable = closable
+ @type = type
+ @auto_close_delay = auto_close_delay
+ end
+
+ def closable?
+ @closable
+ end
+
+ def message
+ @message
+ end
+
+ def alert_type_class
+ case @type
+ when "info"
+ "alert-info-type"
+ when "warning"
+ "alert-warning-type"
+ when "danger"
+ "alert-danger-type"
+ when "success"
+ "alert-success-type"
+ end
+ end
+
+ def alert_icon
+ case @type
+ when "info"
+ "info.svg"
+ when "warning"
+ "warning.svg"
+ when "danger"
+ "danger.svg"
+ when "success"
+ "success.svg"
+ end
+ end
+
+ def auto_close?
+ !@auto_close_delay.nil?
+ end
+
+end
\ No newline at end of file
diff --git a/app/components/display/alert_component/alert_component.html.haml b/app/components/display/alert_component/alert_component.html.haml
new file mode 100644
index 0000000000..d0bc0d5ce6
--- /dev/null
+++ b/app/components/display/alert_component/alert_component.html.haml
@@ -0,0 +1,14 @@
+.alert-container{data: {controller: "alert-component",
+ 'alert-component-auto-close-value': auto_close?,
+ 'alert-component-auto-close-after-value': @auto_close_delay,
+ },
+ class: alert_type_class}
+ .alert-icon{class: alert_type_class}
+ = inline_svg_tag alert_icon
+ .alert-message{class: alert_type_class}
+ = message || content
+ - if closable?
+ .alert-close{"data-action":"click->alert-component#close", class: alert_type_class}
+ = inline_svg_tag "x.svg"
+
+
\ No newline at end of file
diff --git a/app/components/display/alert_component/alert_component_controller.js b/app/components/display/alert_component/alert_component_controller.js
new file mode 100644
index 0000000000..0abf19ddae
--- /dev/null
+++ b/app/components/display/alert_component/alert_component_controller.js
@@ -0,0 +1,19 @@
+import { Controller } from "@hotwired/stimulus";
+
+export default class extends Controller {
+
+ static values = {
+ autoCloseAfter: { type: Number, default: 5000 },
+ autoClose: { type: Boolean, default: false },
+ }
+ connect(){
+ if (this.autoCloseValue){
+ setTimeout(() => {
+ this.close()
+ }, this.autoCloseAfterValue);
+ }
+ }
+ close(){
+ this.element.style.display = "none"
+ }
+}
diff --git a/app/components/infinite_scroll_component/infinite_scroll_component.html.haml b/app/components/infinite_scroll_component/infinite_scroll_component.html.haml
index c0fd9abac8..5bdcb976cc 100644
--- a/app/components/infinite_scroll_component/infinite_scroll_component.html.haml
+++ b/app/components/infinite_scroll_component/infinite_scroll_component.html.haml
@@ -12,5 +12,4 @@
Loading ...
- elsif @current_page == 1
%div.text-wrap
- = render AlertMessageComponent.new(id: "#{@id}_view_alert") do
- = error
+ = render Display::AlertComponent.new { error }
diff --git a/app/components/input/date_component.rb b/app/components/input/date_component.rb
index fe85fa8925..2549e36709 100644
--- a/app/components/input/date_component.rb
+++ b/app/components/input/date_component.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
class Input::DateComponent < Input::InputFieldComponent
- def initialize(label: '', name:, value: Date.today, placeholder: '', error_message: '', helper_text: '')
- super(label: label, name: name, value: value, placeholder: placeholder, error_message: error_message, helper_text: helper_text)
+ def initialize(label: '', name:, value: Date.today, placeholder: '', error_message: '', helper_text: '', id: nil)
+ data_flat_picker = { controller: "flatpickr", flatpickr_date_format: "Y-m-d", flatpickr_alt_input: "true", flatpickr_alt_format: "F j, Y" }
+ super(label: label, name: name, value: value, placeholder: placeholder, error_message: error_message, helper_text: helper_text, data: data_flat_picker, id: id)
end
def call
- render Input::InputFieldComponent.new(label: @label, name: @name, value: @value, placeholder: @placeholder, error_message: @error_message, helper_text: @helper_text, type: 'date')
+ render Input::InputFieldComponent.new(label: @label, name: @name, value: @value, placeholder: @placeholder, error_message: @error_message, helper_text: @helper_text, data: @data, type: 'date', id: @id)
end
end
diff --git a/app/components/input/input_field_component.rb b/app/components/input/input_field_component.rb
index 01ed85ef6d..d026ca0e54 100644
--- a/app/components/input/input_field_component.rb
+++ b/app/components/input/input_field_component.rb
@@ -1,5 +1,5 @@
class Input::InputFieldComponent < ViewComponent::Base
- def initialize(label: "" , name:, value: 'Syphax', type: 'text', placeholder: "", error_message: "", helper_text: "")
+ def initialize(label: "" , name:, value: 'Syphax', type: 'text', placeholder: "", error_message: "", helper_text: "", disabled: false, data: nil, id: '')
@label = label
@name = name
@placeholder = placeholder
@@ -7,6 +7,9 @@ def initialize(label: "" , name:, value: 'Syphax', type: 'text', placeholder: ""
@helper_text = helper_text
@value = value
@type = type
+ @disabled = disabled
+ @id = id
+ @data = data
end
diff --git a/app/components/input/input_field_component/input_field_component.html.haml b/app/components/input/input_field_component/input_field_component.html.haml
index 0bd9f9a103..9500ba74d9 100644
--- a/app/components/input/input_field_component/input_field_component.html.haml
+++ b/app/components/input/input_field_component/input_field_component.html.haml
@@ -6,7 +6,7 @@
- if content
= content
- else
- %input.input-field-component.text-input{name: @name, type: @type, placeholder: @placeholder, style: error_style, value: @value}
+ %input.input-field-component.text-input{class: @disabled ? '' : 'not-disabled', name: @name, type: @type, placeholder: @placeholder, style: error_style, id: @id, data: @data, value: @value, disabled: @disabled}
diff --git a/app/components/input/text_input_component.rb b/app/components/input/text_input_component.rb
index 7a38b3de01..d5cca42ebf 100644
--- a/app/components/input/text_input_component.rb
+++ b/app/components/input/text_input_component.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
class Input::TextInputComponent < Input::InputFieldComponent
- def initialize(label: '', name:, value: nil, placeholder: '', error_message: '', helper_text: '')
- super(label: label, name: name, value: value, placeholder: placeholder, error_message: error_message, helper_text: helper_text)
+ def initialize(label: '', name:, value: nil, placeholder: '', error_message: '', helper_text: '', disabled: false, id: '')
+ super(label: label, name: name, value: value, placeholder: placeholder, error_message: error_message, helper_text: helper_text, disabled: disabled, id: id)
end
def call
- render Input::InputFieldComponent.new(label: @label, name: @name, value: @value, placeholder: @placeholder, error_message: @error_message, helper_text: @helper_text, type: @type)
+ render Input::InputFieldComponent.new(label: @label, name: @name, value: @value, placeholder: @placeholder,
+ error_message: @error_message, helper_text: @helper_text,
+ type: @type, disabled: @disabled)
end
end
diff --git a/app/components/layout/progress_pages_component.rb b/app/components/layout/progress_pages_component.rb
new file mode 100644
index 0000000000..1680e4e494
--- /dev/null
+++ b/app/components/layout/progress_pages_component.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class Layout::ProgressPagesComponent < ViewComponent::Base
+
+ renders_many :pages
+ def initialize(pages_title: [])
+ super
+ @pages_title = pages_title
+ end
+end
diff --git a/app/components/layout/progress_pages_component/progress_pages_component.html.haml b/app/components/layout/progress_pages_component/progress_pages_component.html.haml
new file mode 100644
index 0000000000..f6b02cd67f
--- /dev/null
+++ b/app/components/layout/progress_pages_component/progress_pages_component.html.haml
@@ -0,0 +1,32 @@
+%div.w-100{'data-controller': 'progress-pages'}
+ %div
+ .d-flex.justify-content-center.flex-column
+ .progress-pages-container
+ - @pages_title.each_with_index do |key, index|
+ .progress-item{'data-progress-pages-target': 'pageItem'}
+ %div
+ .outlined-circle{class: index.zero? ? 'outlined-active-circle' : ''}
+ = image_tag("icons/white-check.svg")
+ %span{class: index.zero? ? 'active' : ''}
+ = key.humanize
+ - if index < (@pages_title.size-1)
+ %hr.line
+ %div
+ - pages.each_with_index do |page, index|
+ %div.progress-content{{'data-progress-pages-target': 'pageContent'}, class: index.zero? ? '' : 'hide'}
+ = page
+
+
+ .progress-pages-actions
+ .progress-pages-back-button.hide{'data-action': "click->progress-pages#navigateBack", 'data-progress-pages-target': 'backBtn'}
+ = render Buttons::RegularButtonComponent.new(id: 'progress-pages-back-button', value: "Back", variant: "secondary", size: 'slim',state: 'regular') do |btn|
+ - btn.icon_left do
+ = inline_svg "icons/arrow-left.svg"
+ .progress-pages-next-button{'data-action': "click->progress-pages#navigateNext", 'data-progress-pages-target': 'nextBtn'}
+ = render Buttons::RegularButtonComponent.new(id: 'progress-pages-next-button', value: "Next", size: 'slim', state: 'regular') do |btn|
+ - btn.icon_right do
+ = inline_svg "arrow-right.svg"
+ .progress-pages-next-button.hide{ 'data-progress-pages-target': 'finishBtn'}
+ = render Buttons::RegularButtonComponent.new(id: 'progress-pages-finish-button', value: "Finish", size: 'slim', type: 'submit') do |btn|
+ - btn.icon_right do
+ = inline_svg "icons/white-check.svg"
\ No newline at end of file
diff --git a/app/components/layout/progress_pages_component/progress_pages_component_controller.js b/app/components/layout/progress_pages_component/progress_pages_component_controller.js
new file mode 100644
index 0000000000..146922311a
--- /dev/null
+++ b/app/components/layout/progress_pages_component/progress_pages_component_controller.js
@@ -0,0 +1,87 @@
+import {Controller} from "@hotwired/stimulus";
+
+export default class extends Controller {
+ static targets = ['pageItem','pageContent' ,'backBtn', 'nextBtn', 'finishBtn']
+ connect() {
+ this.pagesItems = this.pageItemTargets
+ this.buttons = [this.backBtnTarget, this.nextBtnTarget, this.finishBtnTarget]
+ this.currentForm = 1
+ }
+
+ navigateBack(){
+ this.navigateForm('back')
+ }
+ navigateNext(){
+ this.navigateForm('next')
+ }
+
+ navigateForm(direction) {
+ if (direction === "next" && this.currentForm < this.pagesItems.length) {
+ this.currentForm += 1
+ this.showForm()
+ } else if (direction === "back" && this.currentForm > 1){
+ this.currentForm -= 1
+ this.showForm()
+ }
+ }
+
+ showForm(){
+ const targetForm = this.currentForm
+ for (let index = 1; index <= this.pagesItems.length; index++) {
+
+ const targetFormDOM = this.pageContentTargets[index - 1];
+
+ const isCurrentForm = targetForm === index;
+
+ targetFormDOM.classList.toggle("hide", !isCurrentForm);
+
+ if (isCurrentForm) {
+ this.updateProgressBar(targetForm);
+ this.updateButtons(targetForm);
+ }
+
+ }
+
+ }
+ updateProgressBar(targetForm) {
+ const progressItemsDOM = document.querySelectorAll(".progress-item > div");
+ const line = document.querySelectorAll(".line");
+
+ progressItemsDOM.forEach((item, index) => {
+ const isPassedSection = index + 1 < targetForm;
+ const isCurrentSection = index + 1 === targetForm;
+
+ item.children[0].classList.toggle("outlined-checked-circle", isPassedSection);
+ item.children[0].classList.toggle("outlined-active-circle", isCurrentSection);
+
+
+ item.children[1].classList.toggle("active", isCurrentSection || isPassedSection);
+
+
+ line[index]?.classList.toggle("active", isPassedSection);
+ });
+ }
+
+ updateButtons(targetForm) {
+
+ switch (targetForm) {
+ case 1:
+ this.showBtn([this.buttons[1]]);
+ break;
+ case this.pagesItems.length:
+ this.showBtn([this.buttons[0], this.buttons[2]]);
+ break;
+ default:
+ this.showBtn([this.buttons[0], this.buttons[1]]);
+ }
+
+ }
+
+ showBtn(btnIds = []) {
+ this.buttons.forEach((btn) => {
+ const targetBtnDOM = btn;
+ const shouldShowBtn = btnIds.includes(btn);
+ targetBtnDOM.classList.toggle("hide", !shouldShowBtn);
+ });
+ }
+}
diff --git a/app/components/nested_form_inputs_component/nested_form_inputs_component.html.haml b/app/components/nested_form_inputs_component/nested_form_inputs_component.html.haml
index 78a23641d1..730ec86f43 100644
--- a/app/components/nested_form_inputs_component/nested_form_inputs_component.html.haml
+++ b/app/components/nested_form_inputs_component/nested_form_inputs_component.html.haml
@@ -31,4 +31,4 @@
%div.add-another-object{data: {action:"click->nested-form#add"}}
= inline_svg 'icons/plus.svg'
%div
- Add another #{@object_name}
\ No newline at end of file
+ Add another #{@object_name}
diff --git a/app/components/select_input_component.rb b/app/components/select_input_component.rb
index 935087fe5b..99a481bb58 100644
--- a/app/components/select_input_component.rb
+++ b/app/components/select_input_component.rb
@@ -13,7 +13,7 @@ def initialize(id:, name:, values:, selected:, multiple: false, open_to_add_valu
end
def call
- select_input_tag(@id, @values, @selected, multiple: @multiple, open_to_add_values: @open_to_add_values)
+ select_input_tag(@name, @values, @selected, multiple: @multiple, open_to_add_values: @open_to_add_values)
end
private
@@ -32,7 +32,7 @@ def select_input_tag(id, values, selected, options = {})
'select-input-open-add-value': open_to_add_values
}
}
- #binding.pry
+
select_tag(id, options_for_select(values, selected), select_html_options)
end
end
diff --git a/app/components/turbo_frame_component/turbo_frame_component.html.haml b/app/components/turbo_frame_component/turbo_frame_component.html.haml
index 0991eb213d..51ce9169ce 100644
--- a/app/components/turbo_frame_component/turbo_frame_component.html.haml
+++ b/app/components/turbo_frame_component/turbo_frame_component.html.haml
@@ -6,4 +6,4 @@
%div.p-3
= render LoaderComponent.new
%div{'data-turbo-frame-error-target': 'errorMessage', style:'display: none; width: 100%'}
- = render AlertMessageComponent.new(id: "#{@id}_error-message", type:'danger')
\ No newline at end of file
+ = render Display::AlertComponent.new(type:'danger')
\ No newline at end of file
diff --git a/app/controllers/concerns/ontology_updater.rb b/app/controllers/concerns/ontology_updater.rb
new file mode 100644
index 0000000000..c45020ce94
--- /dev/null
+++ b/app/controllers/concerns/ontology_updater.rb
@@ -0,0 +1,92 @@
+module OntologyUpdater
+ extend ActiveSupport::Concern
+ include SubmissionUpdater
+ def ontology_from_params
+ ontology = LinkedData::Client::Models::Ontology.new(values: ontology_params)
+ ontology.viewOf = nil unless ontology.isView
+ ontology
+ end
+
+ def save_ontology
+
+ @ontology = save_new_ontology
+
+ if response_error?(@ontology)
+ show_new_errors(@ontology)
+ return
+ end
+
+
+ @submission = save_new_submission(params[:submission], @ontology)
+
+ if response_error?(@submission)
+ @ontology.delete
+ show_new_errors(@submission)
+ else
+ redirect_to "/ontologies/success/#{@ontology.acronym}"
+ end
+ end
+
+ def add_ontology_submission(acronym)
+ @ontology = update_existent_ontology(acronym)
+
+ if @ontology.nil? || response_error?(@ontology)
+ show_new_errors(@ontology)
+ return
+ end
+
+ @submission = @ontology.explore.latest_submission({ display: 'all' })
+ submission_params = submission_params(params[:submission])
+ submission_params = submission_params(ActionController::Parameters.new(@submission.to_hash.delete_if { |k, v| v.nil? || v.respond_to?(:empty?) && v.empty? })).merge(submission_params) if @submission
+ submission_params.delete 'submissionId'
+ @submission = save_new_submission(ActionController::Parameters.new(submission_params), @ontology)
+
+ if response_error?(@submission)
+ show_new_errors(@submission)
+ else
+ redirect_to "/ontologies/success/#{@ontology.acronym}"
+ end
+ end
+
+ def save_new_ontology
+ ontology = ontology_from_params
+ ontology.save
+ end
+
+ def update_existent_ontology(acronym)
+ @ontology = LinkedData::Client::Models::Ontology.find_by_acronym(acronym).first
+ return nil if @ontology.nil?
+
+ @ontology.update_from_params(ontology_params)
+ end
+
+ def save_new_submission(submission_hash, ontology)
+ new_submission_params = submission_hash
+ new_submission_params[:ontology] = ontology.acronym
+ save_submission(new_submission_params)
+ end
+
+ def ontology_params
+ p = params.require(:ontology).permit(:name, :acronym, { administeredBy: [] }, :viewingRestriction, { acl: [] },
+ { hasDomain: [] }, :viewOf,:isView, :subscribe_notifications, { group: [] })
+
+ p[:administeredBy].reject!(&:blank?) if p[:administeredBy]
+ # p[:acl].reject!(&:blank?)
+ p[:hasDomain].reject!(&:blank?) if p[:hasDomain]
+ p[:group].reject!(&:blank?) if p[:group]
+ p.to_h
+ end
+
+ def show_new_errors(object)
+ # TODO optimize
+ @ontologies = LinkedData::Client::Models::Ontology.all(include: 'acronym', include_views: true, display_links: false, display_context: false)
+ @categories = LinkedData::Client::Models::Category.all
+ @groups = LinkedData::Client::Models::Group.all(display_links: false, display_context: false)
+ @user_select_list = LinkedData::Client::Models::User.all.map { |u| [u.username, u.id] }
+ @user_select_list.sort! { |a, b| a[1].downcase <=> b[1].downcase }
+ @errors = response_errors(object)
+ @ontology = ontology_from_params
+ @submission = submission_from_params(params[:submission])
+ render 'ontologies/new'
+ end
+end
diff --git a/app/controllers/concerns/submission_updater.rb b/app/controllers/concerns/submission_updater.rb
index 43746c38e2..d8c63ba724 100644
--- a/app/controllers/concerns/submission_updater.rb
+++ b/app/controllers/concerns/submission_updater.rb
@@ -1,11 +1,15 @@
module SubmissionUpdater
extend ActiveSupport::Concern
- def save_submission(new_submission_hash)
+ def submission_from_params(new_submission_hash)
convert_values_to_types(new_submission_hash)
+ LinkedData::Client::Models::OntologySubmission.new(values: submission_params(new_submission_hash))
+ end
+ def save_submission(new_submission_hash)
+
@ontology = LinkedData::Client::Models::Ontology.find_by_acronym(new_submission_hash[:ontology]).first
- @submission = LinkedData::Client::Models::OntologySubmission.new(values: submission_params(new_submission_hash))
+ @submission = submission_from_params(new_submission_hash)
update_ontology_summary_only
@submission.save(cache_refresh_all: false)
@@ -64,12 +68,12 @@ def update_ontology_summary_only(is_remote = @submission.isRemote)
def convert_values_to_types(new_submission_hash)
unless new_submission_hash[:contact].nil?
- new_submission_hash[:contact] = new_submission_hash[:contact].values
+ new_submission_hash[:contact] = new_submission_hash[:contact].values unless new_submission_hash[:contact].is_a?(Array)
new_submission_hash[:contact].delete_if { |c| c[:name].empty? || c[:email].empty? }
end
# Convert metadata that needs to be integer to int
- @metadata.map do |hash|
+ submission_metadata.map do |hash|
if hash["enforce"].include?("integer")
if !new_submission_hash[hash["attribute"]].nil? && !new_submission_hash[hash["attribute"]].eql?("")
new_submission_hash[hash["attribute"].to_s.to_sym] = Integer(new_submission_hash[hash["attribute"].to_s.to_sym])
@@ -111,7 +115,7 @@ def submission_params(params)
:publication
]
- @metadata.each do |m|
+ submission_metadata.each do |m|
m_attr = m["attribute"].to_sym
diff --git a/app/controllers/ontologies_controller.rb b/app/controllers/ontologies_controller.rb
index f7b9ae2fbb..a50f1797c6 100644
--- a/app/controllers/ontologies_controller.rb
+++ b/app/controllers/ontologies_controller.rb
@@ -7,6 +7,7 @@ class OntologiesController < ApplicationController
include SchemesHelper, ConceptsHelper
include CollectionsHelper
include MappingStatistics
+ include OntologyUpdater
require 'multi_json'
require 'cgi'
@@ -195,26 +196,9 @@ def properties
end
def create
- if params[:commit].eql? 'Cancel'
- redirect_to ontologies_path and return
- end
- @ontology = LinkedData::Client::Models::Ontology.new(values: ontology_params)
- @ontology_saved = @ontology.save
- if response_error?(@ontology_saved)
- @categories = LinkedData::Client::Models::Category.all
- @groups = LinkedData::Client::Models::Group.all(display_links: false, display_context: false)
- @user_select_list = LinkedData::Client::Models::User.all.map { |u| [u.username, u.id] }
- @user_select_list.sort! { |a, b| a[1].downcase <=> b[1].downcase }
- @errors = response_errors(@ontology_saved)
- render 'new'
- else
- if @ontology_saved.summaryOnly
- redirect_to "/ontologies/success/#{@ontology.acronym}"
- else
- redirect_to new_ontology_submission_path(@ontology.acronym)
- end
- end
+ # redirect_to ontologies_path and return if params[:commit].eql? 'Cancel'
+ save_ontology
end
def edit
@@ -239,7 +223,8 @@ def mappings
def new
@ontology = LinkedData::Client::Models::Ontology.new
- @ontologies = LinkedData::Client::Models::Ontology.all(include: 'acronym', include_views: true,display_links: false, display_context: false)
+ @submission = LinkedData::Client::Models::OntologySubmission.new
+ @ontologies = LinkedData::Client::Models::Ontology.all(include: 'acronym', include_views: true, display_links: false, display_context: false)
@categories = LinkedData::Client::Models::Category.all
@groups = LinkedData::Client::Models::Group.all
@user_select_list = LinkedData::Client::Models::User.all.map {|u| [u.username, u.id]}
@@ -454,9 +439,9 @@ def widgets
render partial: 'ontologies/sections/widgets', layout: 'ontology_viewer'
end
end
-
+
def show_licenses
-
+
@metadata = submission_metadata
@ontology = LinkedData::Client::Models::Ontology.find_by_acronym(params[:id]).first
@licenses= ["hasLicense","morePermissions","copyrightHolder"]
@@ -464,28 +449,14 @@ def show_licenses
render partial: 'ontologies/sections/licenses'
end
def ajax_ontologies
-
-
+
+
render json: LinkedData::Client::Models::Ontology.all(include_views: true,
display: 'acronym,name', display_links: false, display_context: false)
end
- private
-
-
-
- def ontology_params
- p = params.require(:ontology).permit(:name, :acronym, { administeredBy:[] }, :viewingRestriction, { acl:[] },
- { hasDomain:[] }, :isView, :viewOf, :subscribe_notifications, {group:[]})
-
- p[:administeredBy].reject!(&:blank?)
- p[:acl].reject!(&:blank?)
- p[:hasDomain].reject!(&:blank?)
- p[:group].reject!(&:blank?)
- p.to_h
- end
-
+ private
def get_views(ontology)
views = ontology.explore.views || []
views.select!{ |view| view.access?(session[:user]) }
diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb
index 03f91c9d6f..7680a62d22 100644
--- a/app/controllers/submissions_controller.rb
+++ b/app/controllers/submissions_controller.rb
@@ -1,5 +1,5 @@
class SubmissionsController < ApplicationController
- include SubmissionsHelper, SubmissionUpdater
+ include SubmissionsHelper, SubmissionUpdater, OntologyUpdater
layout :determine_layout
before_action :authorize_and_redirect, :only => [:edit, :update, :create, :new]
before_action :submission_metadata, only: [:create, :edit, :new, :update, :index]
@@ -28,28 +28,17 @@ def new
@submission = @ontology.explore.latest_submission
@submission ||= LinkedData::Client::Models::OntologySubmission.new
@submission.id = nil
+ @categories = LinkedData::Client::Models::Category.all
+ @groups = LinkedData::Client::Models::Group.all
+ @user_select_list = LinkedData::Client::Models::User.all.map {|u| [u.username, u.id]}
+ @user_select_list.sort! {|a,b| a[1].downcase <=> b[1].downcase}
+ @is_update_ontology = true
end
# Called when form to "Add submission" is submitted
def create
- # Make the contacts an array
- _, submission_params = params[:submission].each.first
- @required_only = !params['required-only'].nil?
- @filters_disabled = true
- @submission_saved = save_submission(submission_params)
- if response_error?(@submission_saved)
- @errors = response_errors(@submission_saved) # see application_controller::response_errors
- if @errors && @errors[:uploadFilePath]
- @errors = ["Please specify the location of your ontology"]
- elsif @errors && @errors[:contact]
- @errors = ["Please enter a contact"]
- end
-
- reset_agent_attributes
- render 'new', status: 422
- else
- redirect_to "/ontologies/success/#{@ontology.acronym}"
- end
+ @is_update_ontology = true
+ add_ontology_submission(params[:ontology][:acronym] || params[:id])
end
# Called when form to "Edit submission" is submitted
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 323f301f11..396f688839 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -34,7 +34,7 @@ def omniauth_providers_info
end
def omniauth_provider_info(strategy)
- omniauth_providers_info.select {|k,v| v[:strategy].eql?(strategy.to_sym)}
+ omniauth_providers_info.select {|k,v| v[:strategy].eql?(strategy.to_sym) || k.eql?(strategy)}
end
def omniauth_token_provider(strategy)
@@ -367,14 +367,14 @@ def get_groups_data
def metadata_for_select
get_metadata
return @metadata_for_select
- end
+ end
def get_metadata
@metadata_for_select = []
submission_metadata.each do |data|
@metadata_for_select << data["attribute"]
end
- end
+ end
def ontologies_to_acronyms(ontologyIDs)
@@ -426,7 +426,7 @@ def add_proposal_button(parent_id, parent_type)
class: "add_proposal btn btn-primary", data: { show_modal_title_value: "Add a new proposal"}
end
end
-
+
def subscribe_button(ontology_id)
ontology_acronym = ontology_id.split('/').last
@@ -611,10 +611,10 @@ def skos?
submission = @submission || @submission_latest
submission&.hasOntologyLanguage === 'SKOS'
end
-
+
def current_page?(path)
request.path.eql?(path)
- end
+ end
def request_lang
lang = params[:language] || params[:lang]
@@ -646,12 +646,9 @@ def bp_config_json
config[:ncbo_slice] = @subdomain_filter[:acronym] if (@subdomain_filter[:active] && !@subdomain_filter[:acronym].empty?)
config.to_json
end
-
-
def portal_name
$SITE
- end
-
+ end
def navitems
items = [["/ontologies", "Browse"],["/mappings", "Mappings"],["/recommender", "Recommender"],["/annotator", "Annotator"], ["/landscape", "Landscape"]]
end
diff --git a/app/helpers/collections_helper.rb b/app/helpers/collections_helper.rb
index 9f6de40089..40783b6666 100644
--- a/app/helpers/collections_helper.rb
+++ b/app/helpers/collections_helper.rb
@@ -42,7 +42,7 @@ def no_collections?
end
def no_collections_alert
- render AlertMessageComponent.new(id: 'collection-empty-info') do
+ render Display::AlertComponent.new do
"#{@ontology.acronym} does not contain collections (skos:Collection)"
end
end
diff --git a/app/helpers/inputs_helper.rb b/app/helpers/inputs_helper.rb
new file mode 100644
index 0000000000..ff0f14294a
--- /dev/null
+++ b/app/helpers/inputs_helper.rb
@@ -0,0 +1,45 @@
+module InputsHelper
+
+ def text_input(label: nil, name: , value:, disabled: false)
+ render Input::TextInputComponent.new(label: input_label(label, name) , name: name, value: value, error_message: input_error_message(name), disabled: disabled)
+ end
+
+ def select_input(label: nil, name: , values:, selected: nil, multiple: false)
+ render Input::SelectComponent.new(label: input_label(label, name), name: name, value: values, selected: selected, multiple: multiple)
+ end
+
+ def check_input(id:, name: , label: '', value:, checked: false)
+ render ChipsComponent.new(name: name, id: id, label: label, value: value, checked: checked)
+ end
+
+ def switch_input(id: , name:, label: ,checked: false)
+ render SwitchInputComponent.new(id: id, name: name, label: label, checked: checked)
+ end
+
+ def url_input(label: nil, name: , value:)
+ render Input::UrlComponent.new(label: input_label(label, name), name: name, value: value, error_message: input_error_message(name) )
+ end
+
+ def text_area_input(label: nil, name: , value:)
+ render Input::TextAreaComponent.new(label: input_label(label, name), name: name, value: value, error_message: input_error_message(name))
+ end
+
+ def date_input(label: nil, name:, value:)
+ render Input::DateComponent.new(label: input_label(label, name) ,name: name, value: value || Date.today, error_message: input_error_message(name))
+ end
+
+ private
+
+ def method_name(name)
+ match = /.*\[(.*?)\]/.match(name)
+ match.nil? ? name : match[1]
+ end
+
+ def input_label(label, name)
+ label || method_name(name).humanize
+ end
+
+ def input_error_message(name)
+ attribute_error(method_name(name))
+ end
+end
\ No newline at end of file
diff --git a/app/helpers/ontologies_helper.rb b/app/helpers/ontologies_helper.rb
index b421e5ae41..cf35e422d5 100644
--- a/app/helpers/ontologies_helper.rb
+++ b/app/helpers/ontologies_helper.rb
@@ -534,10 +534,26 @@ def ontology_edit_button
def submission_json_button
render RoundedButtonComponent.new(link: "#{(@submission_latest || @ontology).id}?display=all", target: '_blank', size: 'medium')
end
+
+ def attribute_error(attr)
+ return '' unless @errors && @errors[attr.to_sym]
+ errors = @errors[attr.to_sym]
+
+ errors.values.join(', ')
+ end
+
+ def error_message
+ if !@errors[:error].nil? && @errors[:error].is_a?(String)
+ @errors[:error]
+ else
+ "Errors in fields #{@errors.keys.join(', ')}"
+ end
+
+ end
private
def submission_languages(submission = @submission)
- submission.naturalLanguage.map { |natural_language| natural_language["iso639"] && natural_language.split('/').last }.compact
+ submission&.naturalLanguage.map { |natural_language| natural_language["iso639"] && natural_language.split('/').last }.compact
end
end
diff --git a/app/helpers/schemes_helper.rb b/app/helpers/schemes_helper.rb
index 01b3993da5..55d59c4e1a 100644
--- a/app/helpers/schemes_helper.rb
+++ b/app/helpers/schemes_helper.rb
@@ -63,12 +63,12 @@ def no_schemes?
end
def no_main_scheme_alert
- render AlertMessageComponent.new(id: 'main-scheme-empty-info') do
+ render Display::AlertComponent.new do
'no main scheme defined in the URI attribute'
end
end
def no_schemes_alert
- render AlertMessageComponent.new(id: 'schemes-empty-info') do
+ render Display::AlertComponent.new do
"#{@ontology.acronym} does not contain schemes (skos:ConceptScheme)"
end
end
diff --git a/app/helpers/submissions_helper.rb b/app/helpers/submissions_helper.rb
index cc338b9942..ca55ce95b5 100644
--- a/app/helpers/submissions_helper.rb
+++ b/app/helpers/submissions_helper.rb
@@ -338,12 +338,7 @@ def generate_agent_input(attr, type: 'person')
def generate_date_input(attr)
field_id = [:submission, attr["attribute"].to_s, @ontology.acronym].join('_')
date_value = @submission.send(attr["attribute"]).presence
- data_flat_picker = { controller: "flatpickr", flatpickr_date_format: "Y-m-d", flatpickr_alt_input: "true", flatpickr_alt_format: "F j, Y" }
- content_tag(:div, class: 'input-group') do
- [
- date_field(object_name, attr["attribute"].to_s.to_sym, value: date_value, id: field_id, data: data_flat_picker, class: "not-disabled")
- ].join.html_safe
- end
+ render Input::DateComponent.new(label: (attr["label"] || attr["attribute"]).to_s ,name: object_name, value: date_value || Date.today, id: field_id)
end
def generate_textarea_input(attr)
@@ -355,10 +350,13 @@ def generate_select_input(attr, name, select_values, metadata_values, multiple:
render SelectInputComponent.new(id: id, name: name, values: select_values , selected: metadata_values , multiple: multiple)
end
- def generate_list_field_input(attr, name, values, field_func)
+ def generate_list_field_input(attr, name, label, values, &block)
render NestedFormInputsComponent.new do |c|
- c.template do
- method(field_func).call("#{name}[NEW_RECORD]", '', :id => attr["attribute"].to_s + "_" + @ontology.acronym, class: "metadataInput form-control my-1")
+ c.header do
+ content_tag(:div, label)
+ end
+ c.template do
+ block.call('', "#{name}[NEW_RECORD]", attr["attribute"].to_s + "_" + @ontology.acronym)
end
c.empty_state do
@@ -367,20 +365,25 @@ def generate_list_field_input(attr, name, values, field_func)
values.each_with_index do |metadata_val, i|
c.row do
- method(field_func).call("#{name}[#{i}]", metadata_val, :id => "submission_#{attr["attribute"].to_s}" + "_" + @ontology.acronym, class: "metadataInput my-1 form-control")
+ block.call(metadata_val, "#{name}[#{i}]" ,"submission_#{attr["attribute"].to_s}" + "_" + @ontology.acronym)
end
end
end
end
- def generate_url_input(attr, name, values)
- generate_list_field_input(attr, name, values, :url_field_tag)
+ def generate_url_input(attr, name, values, label:"")
+ generate_list_field_input(attr, name, label, values) do |value, row_name, id|
+ render Input::UrlComponent.new(label: "", name: row_name, value: value, id: id)
+ end
end
- def generate_list_text_input(attr, name, values)
- generate_list_field_input(attr, name, values, :text_field_tag)
+ def generate_list_text_input(attr, name, values, label:"")
+ generate_list_field_input(attr, name, label, values) do |value, row_name, id|
+ render Input::TextInputComponent.new(label: "", name: row_name, value: value, id: id)
+ end
end
+
def generate_boolean_input(attr, name)
value = attribute_values(attr)
value = value.to_s unless value.nil?
@@ -412,7 +415,7 @@ def generate_attribute_input(attr_label, options = {})
input_html = ''.html_safe
# Get the attribute hash corresponding to the given attribute
- attr = @metadata.select { |attr_hash| attr_hash["attribute"].to_s.eql?(attr_label) }.first
+ attr = submission_metadata.select { |attr_hash| attr_hash["attribute"].to_s.eql?(attr_label) }.first
object_name, name = attribute_input_name(attr["attribute"])
diff --git a/app/helpers/turbo_helper.rb b/app/helpers/turbo_helper.rb
index 3e1f71155f..c1b0303b46 100644
--- a/app/helpers/turbo_helper.rb
+++ b/app/helpers/turbo_helper.rb
@@ -9,7 +9,7 @@ def alerts_container_id(id = nil)
def alert(id: nil, type: 'success', &block)
turbo_stream.prepend(id ||alerts_container_id) do
- AlertMessageComponent.new(type: type).render_in(view_context, &block)
+ Display::AlertComponent.new(type: type).render_in(view_context, &block)
end
end
diff --git a/app/javascript/component_controllers/index.js b/app/javascript/component_controllers/index.js
index 5cb73bbeb5..0a94e7a7eb 100644
--- a/app/javascript/component_controllers/index.js
+++ b/app/javascript/component_controllers/index.js
@@ -16,6 +16,10 @@ import CircleProgressBarComponentController from "../../components/circle_progre
import Tabs_container_component_controller
from "../../components/tabs_container_component/tabs_container_component_controller";
+import alert_component_controller from "../../components/display/alert_component/alert_component_controller";
+import Progress_pages_component_controller
+ from "../../components/layout/progress_pages_component/progress_pages_component_controller";
+
application.register("turbo-modal", TurboModalController)
application.register("file-input", FileInputLoaderController)
@@ -25,3 +29,5 @@ application.register("subscribe-notes", Ontology_subscribe_button_component_cont
application.register("search-input", Search_input_component_controller)
application.register("tabs-container", Tabs_container_component_controller)
application.register("circle-progress-bar", CircleProgressBarComponentController)
+application.register("alert-component", alert_component_controller)
+application.register("progress-pages", Progress_pages_component_controller)
diff --git a/app/javascript/controllers/tom_select_controller.js b/app/javascript/controllers/tom_select_controller.js
new file mode 100644
index 0000000000..4f157b2aaa
--- /dev/null
+++ b/app/javascript/controllers/tom_select_controller.js
@@ -0,0 +1,16 @@
+import { Controller } from "@hotwired/stimulus"
+import TomSelect from "tom-select"
+// Connects to data-controller="tom-select"
+export default class extends Controller {
+
+
+
+ connect() {
+
+ new TomSelect(this.element, {
+
+
+ //plugins: ['remove_button']
+ });
+ }
+}
diff --git a/app/views/concepts/_details.html.haml b/app/views/concepts/_details.html.haml
index a83f051fa7..a98a909b0d 100644
--- a/app/views/concepts/_details.html.haml
+++ b/app/views/concepts/_details.html.haml
@@ -3,7 +3,7 @@
- label_xl_set = %w[skos-xl#prefLabel skos-xl#altLabel skos-xl#hiddenLabel]
- if @concept.prefLabel.nil?
%div.py-3.px-2
- = render(AlertMessageComponent.new(message: t('ontology_details.concept.no_preferred_name_for_selected_language'), type: "warning", closeable: true))
+ = render Display::AlertComponent.new(message: t('ontology_details.concept.no_preferred_name_for_selected_language'), type: "warning", closable: true)
= render ConceptDetailsComponent.new(id:'concept-details', acronym: @ontology.acronym,
properties: @concept.properties,
diff --git a/app/views/layouts/_topnav.html.haml b/app/views/layouts/_topnav.html.haml
index 2da968c7ec..6c8deed355 100644
--- a/app/views/layouts/_topnav.html.haml
+++ b/app/views/layouts/_topnav.html.haml
@@ -44,7 +44,7 @@
= link_to("Logout", logout_path)
= select_tag('language', options_for_select([['EN','en'],['FR','fr']]), id: 'language-select', class: 'nav-language',
- data: { controller: "platform-language", action: "change->platform-language#handleLangChanged" })
+ data: { controller: "platform-language", action: "change->platform-language#handleLangChanged" })
= render DropdownButtonComponent.new do |d|
- d.header do
diff --git a/app/views/layouts/component_preview.html.erb b/app/views/layouts/component_preview.html.erb
index 5369cd0531..429f630109 100644
--- a/app/views/layouts/component_preview.html.erb
+++ b/app/views/layouts/component_preview.html.erb
@@ -55,5 +55,6 @@
<%= javascript_include_tag "application" %>
+