decidim-feeds_ui 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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" %>