diff --git a/app/admin/news_article.rb b/app/admin/news_article.rb index 8e9d5d5cc..b2de584e7 100644 --- a/app/admin/news_article.rb +++ b/app/admin/news_article.rb @@ -6,7 +6,7 @@ decorate_with NewsArticleDecorator - permit_params :title, :content, :publication_date, + permit_params :title, :content, :publication_date, :is_insight, :created_by_id, :updated_by_id, :image, :keywords_string, tpi_sector_ids: [] @@ -30,6 +30,7 @@ row :image do |t| image_tag(url_for(t.image)) if t.image.present? end + row :is_insight row :updated_at row :updated_by row :created_at @@ -43,6 +44,7 @@ index do column 'Title', :title_link column :publication_date + column :is_insight actions end @@ -54,6 +56,7 @@ column(:sectors) { |l| l.tpi_sectors.map(&:name).join(Rails.application.config.csv_options[:entity_sep]) } column :keywords, &:keywords_csv column :publication_date + column :is_insight end form html: {'data-controller' => 'check-modified'} do |f| @@ -67,6 +70,7 @@ collection: TPISector.order(:name), input_html: {multiple: true} f.input :keywords_string, label: 'Keywords', hint: t('hint.tag'), as: :tags, collection: Keyword.pluck(:name) f.input :image, as: :file, input_html: {accept: 'image/*'} + f.input :is_insight end f.actions diff --git a/app/admin/publication.rb b/app/admin/publication.rb index 3b0587e54..2253d9819 100644 --- a/app/admin/publication.rb +++ b/app/admin/publication.rb @@ -7,7 +7,7 @@ decorate_with PublicationDecorator permit_params :title, :author, :author_image, :short_description, :publication_date, - :file, :image, :created_by_id, :updated_by_id, + :file, :image, :created_by_id, :updated_by_id, :summary, :keywords_string, tpi_sector_ids: [] filter :title @@ -20,6 +20,7 @@ attributes_table do row :title row :short_description + row :summary row :author row :author_image do |p| if p.author_image.present? @@ -63,6 +64,7 @@ f.input :author f.input :author_image, as: :file, hint: preview_file_tag(f.object.author_image), input_html: {accept: 'image/*'} f.input :short_description, as: :text + f.input :summary, as: :trix, embed_youtube: true f.input :publication_date, as: :date_time_picker f.input :tpi_sector_ids, label: 'Sectors', as: :select, collection: TPISector.order(:name), input_html: {multiple: true} diff --git a/app/assets/stylesheets/tpi/_pages.scss b/app/assets/stylesheets/tpi/_pages.scss index e55a2fe0b..3678e66f7 100644 --- a/app/assets/stylesheets/tpi/_pages.scss +++ b/app/assets/stylesheets/tpi/_pages.scss @@ -174,6 +174,12 @@ $margin-between-list-items: 20px; flex-direction: column; } } + + &__flex { + display: flex; + gap: 20px; + flex-wrap: wrap; + } } .pages__content-title { diff --git a/app/assets/stylesheets/tpi/_publications.scss b/app/assets/stylesheets/tpi/_publications.scss index d670ad829..f8f9fd804 100644 --- a/app/assets/stylesheets/tpi/_publications.scss +++ b/app/assets/stylesheets/tpi/_publications.scss @@ -257,6 +257,16 @@ $max-lines: 3; margin-bottom: 22px; } } + + &__content-type { + color: $grey-dark; + margin-top: 10px; + font-size: $size-7; + border: 1px solid rgba($grey-dark, 0.5); + padding-left: $size-7; + padding-right: $size-7; + display: inline-block; + } } .publications__grid { diff --git a/app/controllers/tpi/publications_controller.rb b/app/controllers/tpi/publications_controller.rb index 102a510ee..a50b00248 100644 --- a/app/controllers/tpi/publications_controller.rb +++ b/app/controllers/tpi/publications_controller.rb @@ -7,6 +7,7 @@ class PublicationsController < TPIController before_action :fetch_tags, only: [:index] before_action :fetch_sectors, only: [:index] before_action :fetch_publication, only: [:show] + before_action :fetch_news_article, only: [:show_news_article] def index results = Queries::TPI::NewsPublicationsQuery.new(filter_params).call @@ -36,14 +37,17 @@ def show respond_to do |format| format.html do admin_panel_path = polymorphic_path([:admin, @publication]) - fixed_navbar("#{@publication.class.name.underscore.humanize} #{@publication.title}", admin_panel_path) - - redirect_to '' unless @publication + fixed_navbar(@publication.title.to_s, admin_panel_path) end format.pdf { stream_publication_file } end end + def show_news_article + admin_panel_path = polymorphic_path([:admin, @news_article]) + fixed_navbar((@news_article[:title]).to_s, admin_panel_path) + end + def download_file @publication = Publication.published.find_by! slug: params[:slug] stream_publication_file @@ -70,15 +74,15 @@ def offset end def filter_params - params.permit(:tags, :sectors) + params.permit(:tags, :sectors, :types) end def fetch_publication - @publication = if params[:type].eql?('NewsArticle') - NewsArticle.published.find(params[:id]) - else - Publication.published.find_by(id: params[:id]) || Publication.published.find_by!(slug: params[:id]) - end + @publication = Publication.published.find_by(id: params[:id]) || Publication.published.find_by!(slug: params[:id]) + end + + def fetch_news_article + @news_article = NewsArticle.published.find params[:id] end def fetch_tags diff --git a/app/javascript/components/tpi/Filters.js b/app/javascript/components/tpi/Filters.js index 991a52050..a8922c03e 100644 --- a/app/javascript/components/tpi/Filters.js +++ b/app/javascript/components/tpi/Filters.js @@ -9,20 +9,25 @@ import { useQueryParam } from 'shared/hooks'; const ALL_OPTION_NAME = 'All'; const SHOW_ON_PAGE = 9; -const Filters = ({ tags, sectors, resultsSize }) => { +const Filters = ({ types, tags, sectors, resultsSize }) => { const [isFilterOpen, setIsFiltersOpen] = useState(false); const [resultsCount, setResultsCount] = useState(resultsSize); + const [queryTypesParam, setQueryTypes] = useQueryParam('types'); const [queryTagsParam, setQueryTags] = useQueryParam('tags'); const [querySectorsParam, setQuerySectors] = useQueryParam('sectors'); const [offset, setOffset] = useState(0); + const activeTypes = useMemo(() => { + const typesWithAllOption = [ALL_OPTION_NAME, ...types]; + const queryTypes = (queryTypesParam || '').split(',').filter(x => x); + return typesWithAllOption.map(type => ({ + name: type, + active: queryTypes.length > 0 ? queryTypes.includes(type) : type === ALL_OPTION_NAME + })); + }, [types, queryTypesParam]); const activeTags = useMemo(() => { const queryTags = (queryTagsParam || '').split(',').filter(x => x); - const tagsWithAllOption = [ - ALL_OPTION_NAME, - ...queryTags.filter(x => !tags.includes(x)), - ...tags - ]; + const tagsWithAllOption = [ALL_OPTION_NAME, ...tags]; return tagsWithAllOption.map(tag => ({ name: tag, active: queryTags.length > 0 ? queryTags.includes(tag) : tag === ALL_OPTION_NAME @@ -71,7 +76,11 @@ const Filters = ({ tags, sectors, resultsSize }) => { }; }, [handleLoadMore]); - const refreshPublicationsHtml = (_tags, _sectors, _offset) => { + const refreshPublicationsHtml = (_types, _tags, _sectors, _offset) => { + const activeTypesQueryParam = _types + .filter(t => t.active && t.name !== ALL_OPTION_NAME) + .map(t => encodeURIComponent(t.name)) + .join(', '); const activeTagsQueryParam = _tags .filter(t => t.active && t.name !== ALL_OPTION_NAME) .map(t => encodeURIComponent(t.name)) @@ -81,7 +90,7 @@ const Filters = ({ tags, sectors, resultsSize }) => { .map(s => encodeURIComponent(s.name)) .join(', '); - const query = `tags=${activeTagsQueryParam}§ors=${activeSectorsQueryParam}&offset=${_offset}`; + const query = `types=${activeTypesQueryParam}&tags=${activeTagsQueryParam}§ors=${activeSectorsQueryParam}&offset=${_offset}`; const url = `/publications/partial?${query}`; fetch(url) @@ -98,8 +107,31 @@ const Filters = ({ tags, sectors, resultsSize }) => { }; useEffect(() => { - refreshPublicationsHtml(activeTags, activeSectors, offset); - }, [activeTags, activeSectors, offset]); + refreshPublicationsHtml(activeTypes, activeTags, activeSectors, offset); + }, [activeTypes, activeTags, activeSectors, offset]); + + const handleTypeClick = (type) => { + const otherOptions = optionsWithoutALL(activeTypes); + + const shouldALLbeSelected = isAllClicked(type) && (isOtherOptionsActive(otherOptions) || isAllSelected(otherOptions)); + + if (shouldALLbeSelected) { + const typesWithALLSelected = activeTypes.map(s => ({ + name: s.name, + active: s.name === ALL_OPTION_NAME + })); + setOffset(0); + setQueryTypes(typesWithALLSelected.filter(s => s.active).map((s) => s.name).join(',')); + } else { + const updatedTypes = activeTypes.map(s => { + if (s.name === type.name) { return { name: s.name, active: !s.active }; } + if (s.name === ALL_OPTION_NAME) { return { name: s.name, active: false }; } + return { name: s.name, active: s.active }; + }); + setOffset(0); + setQueryTypes(updatedTypes.filter(s => s.active).map((s) => s.name).join(',')); + } + }; const handleTagClick = (tag) => { const otherOptions = optionsWithoutALL(activeTags); @@ -172,6 +204,18 @@ const Filters = ({ tags, sectors, resultsSize }) => { {isFilterOpen && (
<%= @publication.publication_date.strftime('%d/%m/%Y') %>
- <% if @publication.class.name.eql?("NewsArticle") && @publication.image.present? %> -<%= @publication.short_description %>
+ <% if @publication.keywords.any? || @publication.tpi_sectors.any? %> + + <% end %> +<%= @news_article.publication_date.strftime('%d/%m/%Y') %>
+ <% if @news_article.image.present? %> +