decidim-feeds_ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +37 -0
  4. data/Rakefile +9 -0
  5. data/app/controllers/decidim/feeds_ui/admin/application_controller.rb +23 -0
  6. data/app/controllers/decidim/feeds_ui/application_controller.rb +19 -0
  7. data/app/controllers/decidim/feeds_ui/users_controller.rb +47 -0
  8. data/app/helpers/decidim/feeds_ui/application_helper.rb +21 -0
  9. data/app/models/decidim/feeds_ui/application_record.rb +10 -0
  10. data/app/packs/entrypoints/decidim_feeds_ui.js +5 -0
  11. data/app/packs/images/decidim/feeds_ui/DigifondsGefoerdert.png +0 -0
  12. data/app/packs/images/decidim/feeds_ui/icon.svg +1 -0
  13. data/app/packs/images/decidim/feeds_ui/mitgestalten-logo.png +0 -0
  14. data/app/packs/src/decidim/feeds_ui/feeds_ui.js +41 -0
  15. data/app/packs/stylesheets/decidim/feeds_ui/feeds_ui.scss +230 -0
  16. data/app/permissions/decidim/feeds_ui/admin/permissions.rb +23 -0
  17. data/app/permissions/decidim/feeds_ui/permissions.rb +27 -0
  18. data/app/views/decidim/feeds_ui/users/_users_list.html.erb +26 -0
  19. data/app/views/decidim/feeds_ui/users/filter_users.js.erb +2 -0
  20. data/app/views/decidim/feeds_ui/users/index.html.erb +30 -0
  21. data/app/views/decidim/feeds_ui/users/user_profile.html.erb +24 -0
  22. data/app/views/layouts/decidim/_admin_links.html.erb +3 -0
  23. data/app/views/layouts/decidim/_logo.html.erb +10 -0
  24. data/app/views/layouts/decidim/footer/_main.html.erb +4 -0
  25. data/app/views/layouts/decidim/footer/_mini.html.erb +57 -0
  26. data/app/views/layouts/decidim/header/_links_mobile_top.html.erb +32 -0
  27. data/app/views/layouts/decidim/header/_main.html.erb +31 -0
  28. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +31 -0
  29. data/app/views/layouts/decidim/header/_main_links_dropdown.html.erb +39 -0
  30. data/app/views/layouts/decidim/header/_main_links_mobile.html.erb +57 -0
  31. data/app/views/layouts/decidim/header/_menu.html.erb +0 -0
  32. data/config/assets.rb +9 -0
  33. data/config/i18n-tasks.yml +10 -0
  34. data/config/locales/bs.yml +29 -0
  35. data/config/locales/de.yml +29 -0
  36. data/config/locales/en.yml +29 -0
  37. data/config/locales/hr.yml +29 -0
  38. data/config/locales/it.yml +29 -0
  39. data/config/locales/sr.yml +29 -0
  40. data/config/locales/tr.yml +29 -0
  41. data/lib/decidim/feeds_ui/admin.rb +8 -0
  42. data/lib/decidim/feeds_ui/admin_engine.rb +27 -0
  43. data/lib/decidim/feeds_ui/engine.rb +50 -0
  44. data/lib/decidim/feeds_ui/menu.rb +18 -0
  45. data/lib/decidim/feeds_ui/test/factories.rb +7 -0
  46. data/lib/decidim/feeds_ui/version.rb +11 -0
  47. data/lib/decidim/feeds_ui.rb +10 -0
  48. metadata +154 -0
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # Decidim::FeedsUi
2
+
3
+ A mobile ui for the decidim feeds module.
4
+
5
+ ## Usage
6
+
7
+ FeedsUi will add an overview over all users under /feeds_ui/allusers
8
+
9
+ It will also overwrite the decidim layout for a more minimalistic and mobile first interface that is optimal for the [feeds](https://github.com/DecidimAustria/decidim-module-feeds) and [posts](https://github.com/DecidimAustria/decidim-module-posts) modules.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem "decidim-feeds_ui"
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ ```bash
22
+ bundle
23
+ ```
24
+
25
+ ## Contributing
26
+
27
+ Contributions are welcome !
28
+
29
+ We expect the contributions to follow the [Decidim's contribution guide](https://github.com/decidim/decidim/blob/develop/CONTRIBUTING.adoc).
30
+
31
+ ## Security
32
+
33
+ Security is very important to us. If you have any issue regarding security, please disclose the information responsibly by sending an email to __alex [at] rusa [dot] at__ and not by creating a Github issue.
34
+
35
+ ## License
36
+
37
+ This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
4
+
5
+ desc "Generates a dummy app for testing"
6
+ task test_app: "decidim:generate_external_test_app"
7
+
8
+ desc "Generates a development app."
9
+ task development_app: "decidim:generate_external_development_app"
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FeedsUi
5
+ module Admin
6
+ # This controller is the abstract class from which all other controllers of
7
+ # this engine inherit.
8
+ class ApplicationController < Decidim::Admin::ApplicationController
9
+ def permission_class_chain
10
+ [::Decidim::FeedsUi::Admin::Permissions] + super
11
+ end
12
+
13
+ def user_not_authorized_path
14
+ decidim.root_path
15
+ end
16
+
17
+ def user_has_no_permission_path
18
+ decidim.root_path
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FeedsUi
5
+ # This controller is the abstract class from which all other controllers of
6
+ # this engine inherit.
7
+ class ApplicationController < Decidim::ApplicationController
8
+ helper Decidim::FeedsUi::ApplicationHelper
9
+
10
+ def permission_class_chain
11
+ [
12
+ ::Decidim::FeedsUi::Permissions,
13
+ ::Decidim::Permissions
14
+ ]
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FeedsUi
5
+ class UsersController < Decidim::FeedsUi::ApplicationController
6
+ helper Decidim::Messaging::ConversationHelper
7
+
8
+ helper_method :profile_holder, :active_content, :context_menu
9
+
10
+ def index
11
+ enforce_permission_to :read, :users
12
+ @users = confirmed_users
13
+ end
14
+
15
+ def user_profile
16
+ @user = confirmed_users.find(params[:id])
17
+ # Additional logic for displaying the user's profile
18
+ end
19
+
20
+ def profile_holder
21
+ return if params[:nickname].blank?
22
+
23
+ @profile_holder ||= Decidim::UserBaseEntity.find_by("LOWER(nickname) = ? AND decidim_organization_id = ?", params[:nickname].downcase, current_organization.id)
24
+ end
25
+
26
+ def filter_users
27
+ # @user = Decidim::User.find_by(name: params[:name], interest: params[:interest], apartment: params[:apartment])
28
+ query = params[:name].downcase
29
+ @users = confirmed_users.where("lower(name) LIKE ? OR lower(nickname) LIKE ?", "%#{query}%", "%#{query}%")
30
+ respond_to do |format|
31
+ format.js
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def organization_users
38
+ Decidim::User.where(organization: current_organization)
39
+ end
40
+
41
+ def confirmed_users
42
+ organization_users.confirmed.not_deleted
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FeedsUi
5
+ # Custom helpers, scoped to the feeds_ui engine.
6
+ #
7
+ module ApplicationHelper
8
+ def text_initials(name)
9
+ name.split(/[\s.]+/).map(&:chr).slice(0, 2).join.upcase
10
+ end
11
+
12
+ def avatar_url(user)
13
+ if user.avatar.attached?
14
+ user.attached_uploader(:avatar).path(variant: :thumb)
15
+ else
16
+ ActionController::Base.helpers.asset_pack_path("media/images/default-avatar.svg")
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FeedsUi
5
+ # Abstract class from which all models in this engine inherit.
6
+ class ApplicationRecord < ActiveRecord::Base
7
+ self.abstract_class = true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ import 'src/decidim/feeds_ui/feeds_ui.js';
2
+
3
+ require.context('../images', true);
4
+
5
+ import "stylesheets/decidim/feeds_ui/feeds_ui.scss";
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm9.5 13.7H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zm0 3.68H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zM22.26 23H8a1 1 0 0 1 0-1.94h14.26a1 1 0 0 1 0 1.94z"/></svg>
@@ -0,0 +1,41 @@
1
+ document.addEventListener('DOMContentLoaded', function () {
2
+ console.log('Feeds UI loaded');
3
+ const filterOpenButton = document.getElementById(
4
+ 'feedsUI__user_filterButton'
5
+ );
6
+ const filterDiv = document.getElementById('feedsUI__user_filter');
7
+ const userFilterForm = document.getElementById('feedsUI__user_filterForm');
8
+ const fields = userFilterForm.querySelectorAll('input');
9
+
10
+ filterOpenButton.addEventListener('click', function () {
11
+ filterDiv.classList.toggle('active');
12
+ const isExpanded = filterDiv.classList.contains('active');
13
+ filterOpenButton.setAttribute('aria-expanded', isExpanded);
14
+ if (isExpanded) {
15
+ // Focus on the name input when opening
16
+ const firstInput = filterDiv.querySelector('#feedsUI__user_name');
17
+ if (firstInput) {
18
+ firstInput.focus();
19
+ }
20
+ }
21
+ });
22
+
23
+ fields.forEach((field) => {
24
+ field.addEventListener('input', regenerateAjaxCall);
25
+ });
26
+
27
+ function regenerateAjaxCall() {
28
+ const name = document.querySelector('#feedsUI__user_name').value;
29
+ const interest = document.querySelector('#feedsUI__user_interest').value;
30
+ const apartment = document.querySelector('#feedsUI__user_apartment').value;
31
+ const params = new URLSearchParams({
32
+ name: name,
33
+ interest: interest,
34
+ apartment: apartment,
35
+ });
36
+ Rails.ajax({
37
+ url: '/feeds_ui/filter_users?' + params.toString(),
38
+ type: 'GET',
39
+ });
40
+ }
41
+ });
@@ -0,0 +1,230 @@
1
+ /* css for decidim_feeds_ui */
2
+
3
+ /*
4
+ * HEADER
5
+ */
6
+ header {
7
+ .main-bar__avatar {
8
+ @apply border-0 shadow-feedMenu;
9
+ }
10
+ .main-bar__links-mobile-top {
11
+ @apply flex gap-2 lg:hidden;
12
+ > *:first-child {
13
+ @apply flex-grow flex gap-2 justify-center;
14
+ }
15
+ .links-mobile-top__item {
16
+ @apply flex gap-1 items-center text-xs font-medium rounded-2xl shadow-feedMenu py-1 px-2 w-fit;
17
+ svg {
18
+ @apply fill-black w-[16px] h-auto;
19
+ }
20
+ &[data-target*='dropdown'] {
21
+ span {
22
+ @apply text-xs font-medium;
23
+ }
24
+ svg {
25
+ @apply w-[16px] h-auto;
26
+ }
27
+ }
28
+ &.notification {
29
+ @apply shadow-feedNotification w-8 h-8 rounded-full;
30
+ svg {
31
+ @apply w-4 h-auto fill-feeds-notification;
32
+ }
33
+ }
34
+ &.active {
35
+ @apply shadow-feedNotification;
36
+ svg {
37
+ @apply fill-feeds-notification;
38
+ }
39
+ }
40
+ }
41
+ }
42
+ .main-bar__links-mobile {
43
+ @apply inset-x-2 bottom-2 w-auto rounded-2xl shadow-feedMenu;
44
+ .main-bar__links-mobile__item {
45
+ @apply justify-between w-1/5 text-xs;
46
+ svg {
47
+ @apply w-[24px] h-auto fill-black;
48
+ }
49
+ &.circle {
50
+ svg {
51
+ @apply w-[48px] h-auto fill-black rotate-45;
52
+ }
53
+ }
54
+ span {
55
+ @apply text-black;
56
+ }
57
+ &.active {
58
+ span {
59
+ @apply text-feeds-notification;
60
+ }
61
+ svg {
62
+ @apply fill-feeds-notification;
63
+ }
64
+ }
65
+ &.notification {
66
+ @apply gap-0 relative;
67
+ span.notification {
68
+ @apply absolute top-0 right-4 w-3 h-3 bg-feeds-notification rounded-full;
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ @media (max-width: 768px) {
76
+ header {
77
+ .main-bar {
78
+ @apply flex gap-4 items-center bg-white fixed left-0 right-0 z-30;
79
+ > *:last-child {
80
+ @apply grow;
81
+ }
82
+ }
83
+ .container:has(.flash) {
84
+ @apply absolute top-[72px] left-0 right-0 z-50 bg-white;
85
+ .flash {
86
+ @apply m-0 py-2;
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ @media (max-width: 1024px) {
93
+ header {
94
+ .main-bar {
95
+ .main-bar__search {
96
+ @apply hidden;
97
+ }
98
+ }
99
+ #menu-bar {
100
+ @apply hidden;
101
+ }
102
+ }
103
+ }
104
+
105
+ /*
106
+ * Translation Bar
107
+ */
108
+ .translation-bar {
109
+ @apply max-lg:pr-[91px] md:pr-[101px] lg:pr-0 w-full xl:max-w-screen-xl 2xl:max-w-screen-2xl mx-auto px-4 lg:px-16;
110
+ a {
111
+ @apply border-black p-0.5 max-lg:block max-w-fit mb-2;
112
+ }
113
+ }
114
+
115
+ /*
116
+ * Content
117
+ */
118
+
119
+ #content {
120
+ @apply max-lg:mt-[72px];
121
+ }
122
+
123
+ main.feeds__main {
124
+ @apply flex w-full xl:max-w-screen-xl 2xl:max-w-screen-2xl mx-auto p-4 lg:p-16 lg:pt-0 lg:flex-row lg:gap-4 lg:justify-between;
125
+ }
126
+
127
+ .feedsUI__user {
128
+ @apply w-full max-w-screen-2xl mx-auto p-4 lg:p-16;
129
+ .feedsUI__user_filter {
130
+ @apply h-0 invisible motion-safe:transition-transform;
131
+ &.active {
132
+ @apply h-auto visible;
133
+ }
134
+ }
135
+ }
136
+
137
+ /*
138
+ FOOTER
139
+ */
140
+ footer {
141
+ @apply mb-0;
142
+ .mini-footer {
143
+ position: relative;
144
+ z-index: 20;
145
+ background-color: #f6f8fa !important;
146
+ padding: 0;
147
+ padding-bottom: 80px;
148
+ color: #3c3934 !important;
149
+ * {
150
+ color: #3c3934 !important;
151
+ }
152
+ .row {
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ gap: 0.5rem;
157
+ line-height: 1.5rem;
158
+ padding: 0.5rem 0;
159
+ transition: all ease 500ms;
160
+ @media (min-width: 1024px) {
161
+ padding: 1rem 0;
162
+ gap: 1rem;
163
+ a.small_logo {
164
+ margin: 0;
165
+ }
166
+ }
167
+
168
+ &.logos {
169
+ justify-content: space-between;
170
+ .external-link-indicator {
171
+ display: none;
172
+ }
173
+ }
174
+ a.small_logo {
175
+ margin: 0.5rem 0;
176
+ }
177
+ .external-link-container {
178
+ padding-left: 0.1rem;
179
+ padding-inline-start: 0.1rem;
180
+ padding-right: 0.1rem;
181
+ padding-inline-end: 0.1rem;
182
+ }
183
+ &.footer_mitgestalten {
184
+ font-size: 0.8rem;
185
+ font-weight: 500;
186
+ text-transform: uppercase;
187
+ .mitgestalten_logo {
188
+ max-height: 50px;
189
+ }
190
+ }
191
+ img {
192
+ max-width: 125px;
193
+ }
194
+ }
195
+ nav {
196
+ ul {
197
+ justify-content: center;
198
+ flex-direction: row;
199
+ gap: 1rem;
200
+ flex-wrap: wrap;
201
+ }
202
+ padding-block: 1rem;
203
+ }
204
+ }
205
+ .main-footer a,
206
+ .mini-footer a,
207
+ .footer-social .icon {
208
+ transition: color 0.2s ease-in;
209
+ &:hover {
210
+ text-decoration: none;
211
+ }
212
+ }
213
+ .main-footer a,
214
+ .mini-footer a :not(.icona) {
215
+ text-decoration: underline;
216
+ }
217
+ a.small_logo {
218
+ height: 1.5rem;
219
+ .svg-logo {
220
+ height: 1.5rem;
221
+ width: auto;
222
+ text-decoration: underline;
223
+ transition: color 0.2s ease-in;
224
+ margin: 0 0.5rem;
225
+ &:hover {
226
+ text-decoration: none;
227
+ }
228
+ }
229
+ }
230
+ }
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FeedsUi
5
+ module Admin
6
+ class Permissions < Decidim::DefaultPermissions
7
+ def permissions
8
+ return permission_action if permission_action.scope != :admin
9
+ return permission_action unless user&.admin?
10
+
11
+ allow! if can_access?
12
+
13
+ permission_action
14
+ end
15
+
16
+ def can_access?
17
+ permission_action.subject == :feeds_ui &&
18
+ permission_action.action == :read
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FeedsUi
5
+ class Permissions < Decidim::DefaultPermissions
6
+ def permissions
7
+ return permission_action unless user
8
+
9
+ case permission_action.subject
10
+ when :users
11
+ case permission_action.action
12
+ when :read
13
+ allow! if can_access?
14
+ end
15
+ end
16
+
17
+ permission_action
18
+ end
19
+
20
+ private
21
+
22
+ def can_access?
23
+ user.present?
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ <% if @users.empty? %>
2
+ <li class="pl-4 pr-6 py-4 m-4 bg-white rounded-2xl shadow text-md font-bold">
3
+ <%= t("decidim.components.feeds_ui.user.filter.noUser") %>
4
+ </li>
5
+ <% else %>
6
+ <% @users.each do |user| %>
7
+ <li>
8
+ <%= link_to Decidim::UserPresenter.new(user).profile_url, class: "grow shrink basis-0 pl-4 pr-6 py-4 m-4 bg-white rounded-2xl shadow justify-between items-center gap-4 flex" do %>
9
+ <div class="py-2 flex-col justify-start items-start flex">
10
+ <span class="font-semibold"><%= user.name %></span>
11
+ <span>@<%= user.nickname %></span>
12
+ </div>
13
+ <span class="rounded-full w-[50px] h-[50px] overflow-hidden">
14
+ <% if user.avatar.attached? %>
15
+ <%= image_tag(
16
+ user.attached_uploader(:avatar).path(),
17
+ alt: decidim_sanitize(user.nickname),
18
+ class: 'block w-full h-full object-cover'
19
+ )
20
+ %>
21
+ <% end %>
22
+ </span>
23
+ <% end %>
24
+ </li>
25
+ <% end %>
26
+ <% end %>
@@ -0,0 +1,2 @@
1
+ var usersDisplay = document.querySelector('.user_display ul');
2
+ usersDisplay.innerHTML = '<%= j(render partial: "users_list", locals: { users: @users }) %>';
@@ -0,0 +1,30 @@
1
+ <main class="feedsUI__user min-h-[calc(100vh-72px)]">
2
+ <button id="feedsUI__user_filterButton" class="justify-start items-center gap-1 inline-flex my-4 mx-2 p-2 font-bold text-md" aria-expanded="false" aria-controls="feedsUI__user_filter">
3
+ <%= icon "filter-2-line", class: "h-[20px] w-auto" %><span><%= t("decidim.components.feeds_ui.user.filter.title") %></span>
4
+ </button>
5
+ <div id="feedsUI__user_filter" class="feedsUI__user_filter">
6
+ <%= form_tag(decidim_feeds_ui.allusers_path, method: :get, id: "feedsUI__user_filterForm", remote: true, class: "flex flex-col gap-4 px-4 pt-0 pb-4") do %>
7
+ <%= label_tag :name, class: "flex flex-col gap-1" do %>
8
+ <%= t("decidim.components.feeds_ui.user.filter.name") %>
9
+ <%= text_field_tag :name, params[:name], id: "feedsUI__user_name", class: "reset-defaults p-4 border border-gray rounded-md", autocomplete: "off" %>
10
+ <% end %>
11
+ <%= label_tag :interest, class: "flex flex-col gap-1 hidden" do %>
12
+ <%= t("decidim.components.feeds_ui.user.filter.interest") %>
13
+ <%= text_field_tag :interest, params[:interest], id: "feedsUI__user_interest", class: "reset-defaults p-4 border border-gray rounded-md hidden", autocomplete: "off" %>
14
+ <% end %>
15
+ <%= label_tag :apartment, class: "flex flex-col gap-1 hidden" do %>
16
+ <%= t("decidim.components.feeds_ui.user.filter.block") %>
17
+ <%= text_field_tag :apartment, params[:apartment], id: "feedsUI__user_apartment", class: "reset-defaults p-4 border border-gray rounded-md hidden", autocomplete: "off" %>
18
+ <% end %>
19
+ <% end %>
20
+ </div>
21
+ <div class="user_display" aria-live="polite">
22
+ <ul>
23
+ <%= render partial: "users_list", locals: { users: @users } %>
24
+ </ul>
25
+ </div>
26
+ </main>
27
+ <%= append_javascript_pack_tag "decidim_feeds_ui" %>
28
+ <style>
29
+ .decidim-accessibility-badge{display:none;}
30
+ </style>
@@ -0,0 +1,24 @@
1
+ <main class="feedsUI__user px-4">
2
+ <div class="flex mt-4 gap-4">
3
+ <div class="w-1/2 flex flex-col">
4
+ <h1 class="text-xl font-bold h2"><%= @user.name %></h1>
5
+ <p class="text-base">@<%= @user.nickname %></p>
6
+ <%# if @user.direct_messages_enabled?(context) %>
7
+ <%= link_to current_or_new_conversation_path_with(@user), class: "flex gap-1 mt-4 items-center" do %>
8
+ <%= icon "mail-send-line" %>
9
+ <span><%= t("decidim.profiles.show.send_private_message") %></span>
10
+ <% end %>
11
+ <%# end %>
12
+ </div>
13
+ <div class="w-1/2">
14
+ <% if @user.avatar.attached? %>
15
+ <%= image_tag @user.attached_uploader(:avatar).path(), alt: t("decidim.author.avatar", name: decidim_sanitize(@user.name)), class: "w-[250px] h-[250px] object-cover rounded-md" %>
16
+ <% end %>
17
+ </div>
18
+ </div>
19
+
20
+ <div class="py-8 px-4">
21
+ <%= @user.about.to_s%>
22
+ </div>
23
+
24
+ </main>
@@ -0,0 +1,3 @@
1
+ <%
2
+ # empty to overwrite the core admin_links partial
3
+ %>
@@ -0,0 +1,10 @@
1
+ <% if current_user %>
2
+ <%= link_to decidim.account_path do %>
3
+ <span class="main-bar__avatar">
4
+ <%= image_tag(
5
+ Decidim::UserPresenter.new(current_user).avatar_url(:thumb),
6
+ alt: t("decidim.author.avatar", name: decidim_sanitize(current_user.nickname))
7
+ ) %>
8
+ </span>
9
+ <% end %>
10
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <% if current_user.present? %>
2
+ <%= render partial: "decidim/posts/posts/form.html" %>
3
+ <% end %>
4
+ <%= append_javascript_pack_tag "decidim_feeds" %>