diff --git a/app/components/project_submissions/item_component.html.erb b/app/components/project_submissions/item_component.html.erb
index 0f743e737a..357e222f40 100644
--- a/app/components/project_submissions/item_component.html.erb
+++ b/app/components/project_submissions/item_component.html.erb
@@ -2,8 +2,8 @@
- <%= render ProjectSubmissions::LikeComponent.new(project_submission) %>
-
<%= project_submission.user.username %>
+ <%= render ProjectSubmissions::LikeComponent.new(project_submission:, current_users_submission: current_users_submission?) %>
+ <%= title %>
@@ -27,7 +27,7 @@
class="hidden absolute right-0 z-10 mt-2 w-32 origin-top-right rounded-md bg-white dark:bg-gray-700 py-2 shadow-lg ring-1 ring-gray-900/5 dark:ring-gray-300/5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="options-menu-0-button" tabindex="-1">
<% if project_submission.user == current_user %>
- <%= link_to edit_lesson_v2_project_submission_path(project_submission.lesson, project_submission), class: 'text-gray-700 dark:text-gray-300 group flex items-center px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-gray-200', role: 'menuitem', tabindex: '-1', data: { turbo_frame: 'modal', test_id: 'edit-submission', action: 'click->visibility#off'} do %>
+ <%= link_to edit_path, class: 'text-gray-700 dark:text-gray-300 group flex items-center px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-gray-200', role: 'menuitem', tabindex: '-1', data: { turbo_frame: 'modal', test_id: 'edit-submission', action: 'click->visibility#off'} do %>
<%= inline_svg_tag 'icons/pencil-square.svg', class: 'mr-3 h-4 w-4 text-gray-400 group-hover:text-gray-500 dark:group-hover:text-gray-300', aria: true, title: 'edit', desc: 'edit icon' %>
Edit
<% end %>
diff --git a/app/components/project_submissions/item_component.rb b/app/components/project_submissions/item_component.rb
index 02989597c2..cf40aa42d4 100644
--- a/app/components/project_submissions/item_component.rb
+++ b/app/components/project_submissions/item_component.rb
@@ -3,10 +3,12 @@ class ItemComponent < ApplicationComponent
CURRENT_USER_SORT_CODE = 10_000_000 # current user's submission should always be first
with_collection_parameter :project_submission
+ renders_one :title, ProjectSubmissions::TitleComponent
- def initialize(project_submission:, current_user:)
+ def initialize(project_submission:, current_user:, edit_path: nil)
@project_submission = project_submission
@current_user = current_user
+ @edit_path = edit_path
end
def render?
@@ -17,10 +19,20 @@ def render?
attr_reader :project_submission, :current_user
+ def current_users_submission?
+ project_submission.user == current_user
+ end
+
def sort_code
- return CURRENT_USER_SORT_CODE if project_submission.user == current_user
+ return CURRENT_USER_SORT_CODE if current_users_submission?
project_submission.cached_votes_total
end
+
+ def edit_path
+ return @edit_path if @edit_path.present?
+
+ edit_lesson_v2_project_submission_path(project_submission.lesson, project_submission)
+ end
end
end
diff --git a/app/components/project_submissions/like_component.html.erb b/app/components/project_submissions/like_component.html.erb
index ec948e01c7..f3f10805c6 100644
--- a/app/components/project_submissions/like_component.html.erb
+++ b/app/components/project_submissions/like_component.html.erb
@@ -1,5 +1,5 @@
<%= turbo_frame_tag dom_id(project_submission, :likes) do %>
- <%= button_to project_submission_v2_like_path(project_submission), method: http_action, class: 'text-gray-400 mr-4 flex items-center hint--top', data: { test_id: 'like-submission' }, aria: { label: 'Like submission' } do %>
+ <%= button_to project_submission_v2_like_path(project_submission), method: http_action, disabled: current_users_submission, class: "text-gray-400 mr-4 flex items-center #{'hint--top' unless current_users_submission}", data: { test_id: 'like-submission' }, aria: { label: 'Like submission' } do %>
<%= project_submission.cached_votes_total %>
<%= inline_svg_tag 'icons/heart.svg', class: "h-5 w-5 #{bg_color_class}", aria: true, title: 'heart', desc: 'heart icon' %>
<% end %>
diff --git a/app/components/project_submissions/like_component.rb b/app/components/project_submissions/like_component.rb
index a772b33c33..6f921231dd 100644
--- a/app/components/project_submissions/like_component.rb
+++ b/app/components/project_submissions/like_component.rb
@@ -1,19 +1,22 @@
module ProjectSubmissions
class LikeComponent < ApplicationComponent
- def initialize(project_submission)
+ def initialize(project_submission:, current_users_submission: false)
@project_submission = project_submission
+ @current_users_submission = current_users_submission
end
private
- attr_reader :project_submission
+ attr_reader :project_submission, :current_users_submission
def http_action
project_submission.liked? ? :delete : :post
end
def bg_color_class
- project_submission.liked? ? 'text-teal-700' : 'text-gray-400'
+ return 'text-teal-700' if current_users_submission || project_submission.liked?
+
+ 'text-gray-400'
end
end
end
diff --git a/app/components/project_submissions/title_component.html.erb b/app/components/project_submissions/title_component.html.erb
new file mode 100644
index 0000000000..80cd2626d9
--- /dev/null
+++ b/app/components/project_submissions/title_component.html.erb
@@ -0,0 +1,5 @@
+<% if url.present? %>
+ <%= link_to title, url, class: 'truncate max-w-xs lgs:max-w-lg font-medium text-lg break-words hover:text-gray-800', data: { turbo_frame: '_top' } %>
+<% else %>
+
<%= title %>
+<% end %>
diff --git a/app/components/project_submissions/title_component.rb b/app/components/project_submissions/title_component.rb
new file mode 100644
index 0000000000..6b0e534c42
--- /dev/null
+++ b/app/components/project_submissions/title_component.rb
@@ -0,0 +1,12 @@
+module ProjectSubmissions
+ class TitleComponent < ApplicationComponent
+ def initialize(title:, url: nil)
+ @title = title
+ @url = url
+ end
+
+ private
+
+ attr_reader :title, :url
+ end
+end
diff --git a/app/controllers/lessons/v2_project_submissions_controller.rb b/app/controllers/lessons/v2_project_submissions_controller.rb
index 6366bdd9a2..8503164ace 100644
--- a/app/controllers/lessons/v2_project_submissions_controller.rb
+++ b/app/controllers/lessons/v2_project_submissions_controller.rb
@@ -21,6 +21,8 @@ def create
respond_to do |format|
if @project_submission.save
+ @project_submission.like!(current_user)
+
format.html { redirect_to lesson_path(@lesson), notice: 'Project submitted' }
format.turbo_stream
else
diff --git a/app/controllers/users/project_submissions_controller.rb b/app/controllers/users/project_submissions_controller.rb
new file mode 100644
index 0000000000..c3fa948e96
--- /dev/null
+++ b/app/controllers/users/project_submissions_controller.rb
@@ -0,0 +1,27 @@
+module Users
+ class ProjectSubmissionsController < ApplicationController
+ before_action :authenticate_user!
+
+ def edit
+ @project_submission = current_user.project_submissions.find(params[:id])
+ end
+
+ def update
+ @project_submission = current_user.project_submissions.find(params[:id])
+
+ respond_to do |format|
+ if @project_submission.update(project_submission_params)
+ format.turbo_stream
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ private
+
+ def project_submission_params
+ params.require(:project_submission).permit(:repo_url, :live_preview_url, :is_public)
+ end
+ end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index b2ce9e4a93..9d7d298f75 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -3,5 +3,6 @@ class UsersController < ApplicationController
def show
@courses = current_user.path.courses
+ @project_submissions = current_user.project_submissions.includes(:lesson).order(created_at: :desc)
end
end
diff --git a/app/queries/lesson_project_submissions_query.rb b/app/queries/lesson_project_submissions_query.rb
index c4332c5cae..cf485c81d0 100644
--- a/app/queries/lesson_project_submissions_query.rb
+++ b/app/queries/lesson_project_submissions_query.rb
@@ -14,6 +14,7 @@ def current_user_submission
def public_submissions
lesson.project_submissions
.only_public
+ .includes(:user)
.not_removed_by_admin
.where.not(user: current_user)
.order(cached_votes_total: :desc, created_at: :desc)
diff --git a/app/views/lessons/v2_project_submissions/create.turbo_stream.erb b/app/views/lessons/v2_project_submissions/create.turbo_stream.erb
index 740116a61c..6295906871 100644
--- a/app/views/lessons/v2_project_submissions/create.turbo_stream.erb
+++ b/app/views/lessons/v2_project_submissions/create.turbo_stream.erb
@@ -1,5 +1,7 @@
<%= turbo_stream.prepend "submissions-list" do %>
- <%= render ProjectSubmissions::ItemComponent.new(project_submission: @project_submission, current_user: current_user) %>
+ <%= render ProjectSubmissions::ItemComponent.new(project_submission: @project_submission, current_user:) do |component| %>
+ <%= component.with_title(title: current_user.username, url: dashboard_path) %>
+ <% end %>
<% end %>
<%= turbo_stream.update "add-submission-button", "" %>
diff --git a/app/views/lessons/v2_project_submissions/edit.html.erb b/app/views/lessons/v2_project_submissions/edit.html.erb
index b89db18b18..bc0e27434f 100644
--- a/app/views/lessons/v2_project_submissions/edit.html.erb
+++ b/app/views/lessons/v2_project_submissions/edit.html.erb
@@ -1,3 +1,3 @@
<%= render ModalComponent.new(title: 'Update your project') do %>
- <%= render 'lessons/v2_project_submissions/form', project_submission: @project_submission, url: lesson_v2_project_submission_path(@lesson, @project_submission) %>
+ <%= render 'project_submissions/form', project_submission: @project_submission, url: lesson_v2_project_submission_path(@lesson, @project_submission) %>
<% end %>
diff --git a/app/views/lessons/v2_project_submissions/index.html.erb b/app/views/lessons/v2_project_submissions/index.html.erb
index ee12d2904c..d6d97b3937 100644
--- a/app/views/lessons/v2_project_submissions/index.html.erb
+++ b/app/views/lessons/v2_project_submissions/index.html.erb
@@ -27,8 +27,16 @@
<%= turbo_frame_tag 'submissions-list', data: { test_id: 'submissions-list', controller: 'sort' } do %>
- <%= render ProjectSubmissions::ItemComponent.new(project_submission: @current_user_submission, current_user:) %>
- <%= render ProjectSubmissions::ItemComponent.with_collection(@project_submissions, current_user:) %>
+ <%= render ProjectSubmissions::ItemComponent.new(project_submission: @current_user_submission, current_user:) do |component| %>
+ <%= component.with_title(title: current_user.username, url: dashboard_path) %>
+ <% end %>
+
+ <% @project_submissions.each do |project_submission| %>
+ <%= render ProjectSubmissions::ItemComponent.new(project_submission:, current_user:) do |component| %>
+ <%= component.with_title(title: project_submission.user.username) %>
+ <% end %>
+ <% end %>
+
<% end %>
<% end %>
diff --git a/app/views/lessons/v2_project_submissions/new.html.erb b/app/views/lessons/v2_project_submissions/new.html.erb
index b78d1eecdb..1c872830c2 100644
--- a/app/views/lessons/v2_project_submissions/new.html.erb
+++ b/app/views/lessons/v2_project_submissions/new.html.erb
@@ -1,3 +1,3 @@
<%= render ModalComponent.new(title: 'Submit your project') do %>
- <%= render 'lessons/v2_project_submissions/form', project_submission: @project_submission, url: lesson_v2_project_submissions_path(@lesson) %>
+ <%= render 'project_submissions/form', project_submission: @project_submission, url: lesson_v2_project_submissions_path(@lesson) %>
<% end %>
diff --git a/app/views/lessons/v2_project_submissions/update.turbo_stream.erb b/app/views/lessons/v2_project_submissions/update.turbo_stream.erb
index 8669c54adb..d8d8aafc88 100644
--- a/app/views/lessons/v2_project_submissions/update.turbo_stream.erb
+++ b/app/views/lessons/v2_project_submissions/update.turbo_stream.erb
@@ -1,3 +1,5 @@
<%= turbo_stream.replace @project_submission do %>
- <%= render ProjectSubmissions::ItemComponent.new(project_submission: @project_submission, current_user: current_user) %>
+ <%= render ProjectSubmissions::ItemComponent.new(project_submission: @project_submission, current_user:) do |component| %>
+ <%= component.with_title(title: current_user.username, url: dashboard_path) %>
+ <% end %>
<% end %>
diff --git a/app/views/lessons/v2_project_submissions/_form.html.erb b/app/views/project_submissions/_form.html.erb
similarity index 100%
rename from app/views/lessons/v2_project_submissions/_form.html.erb
rename to app/views/project_submissions/_form.html.erb
diff --git a/app/views/project_submissions/v2_likes/create.turbo_stream.erb b/app/views/project_submissions/v2_likes/create.turbo_stream.erb
index c6650f5814..47744d9209 100644
--- a/app/views/project_submissions/v2_likes/create.turbo_stream.erb
+++ b/app/views/project_submissions/v2_likes/create.turbo_stream.erb
@@ -1,3 +1,5 @@
<%= turbo_stream.replace @project_submission do %>
- <%= render ProjectSubmissions::ItemComponent.new(project_submission: @project_submission, current_user: current_user) %>
+ <%= render ProjectSubmissions::ItemComponent.new(project_submission: @project_submission, current_user:) do |component| %>
+ <%= component.with_title(title: @project_submission.user.username) %>
+ <% end %>
<% end %>
diff --git a/app/views/users/_project_submissions.html.erb b/app/views/users/_project_submissions.html.erb
index a293844e70..5d95d33f21 100644
--- a/app/views/users/_project_submissions.html.erb
+++ b/app/views/users/_project_submissions.html.erb
@@ -1,15 +1,25 @@
Project Submissions
- <% if project_submissions.any? %>
- <%= react_component(
- 'project-submissions/user-project-submissions',
- {
- userId: current_user&.id,
- submissions: project_submissions.map { |submission| ProjectSubmissionSerializer.as_json(submission, current_user) },
- }
- ) %>
+<% if project_submissions.any? %>
+ <% if Feature.enabled?(:v2_project_submissions, current_user) %>
+
+ <% project_submissions.each do |project_submission| %>
+ <%= render ProjectSubmissions::ItemComponent.new(project_submission:, current_user:, edit_path: edit_users_project_submission_path(project_submission)) do |component| %>
+ <%= component.with_title(title: project_submission.lesson.display_title, url: lesson_path(project_submission.lesson)) %>
+ <% end %>
+ <% end %>
+
<% else %>
-
No submissions yet
+ <%= react_component(
+ 'project-submissions/user-project-submissions',
+ {
+ userId: current_user&.id,
+ submissions: project_submissions.map { |submission| ProjectSubmissionSerializer.as_json(submission, current_user) },
+ }
+ ) %>
<% end %>
+<% else %>
+
No submissions yet
+<% end %>
diff --git a/app/views/users/project_submissions/edit.html.erb b/app/views/users/project_submissions/edit.html.erb
new file mode 100644
index 0000000000..bfc41f885a
--- /dev/null
+++ b/app/views/users/project_submissions/edit.html.erb
@@ -0,0 +1,3 @@
+<%= render ModalComponent.new(title: 'Update your project') do %>
+ <%= render 'project_submissions/form', project_submission: @project_submission, url: users_project_submission_path(@project_submission) %>
+<% end %>
diff --git a/app/views/users/project_submissions/update.turbo_stream.erb b/app/views/users/project_submissions/update.turbo_stream.erb
new file mode 100644
index 0000000000..6e8c1877a5
--- /dev/null
+++ b/app/views/users/project_submissions/update.turbo_stream.erb
@@ -0,0 +1,5 @@
+<%= turbo_stream.replace @project_submission do %>
+ <%= render ProjectSubmissions::ItemComponent.new(project_submission: @project_submission, current_user:, edit_path: edit_users_project_submission_path(@project_submission)) do |component| %>
+ <%= component.with_title(title: @project_submission.lesson.display_title, url: lesson_path(@project_submission.lesson)) %>
+ <% end %>
+<% end %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 00ef5ac748..8e3c079f41 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -24,7 +24,7 @@
<%= render partial: 'skill', collection: @courses, as: :course %>
- <%= render 'project_submissions', project_submissions: current_user.project_submissions %>
+ <%= render 'project_submissions', project_submissions: @project_submissions %>
<%= render 'shared/bottom_cta',
diff --git a/config/routes.rb b/config/routes.rb
index 28053b5e2e..a4a7cde5de 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -78,6 +78,7 @@
resources :paths, only: :create
resources :progress, only: :destroy
resource :profile, only: %i[edit update]
+ resources :project_submissions, only: %i[edit update]
end
namespace :lessons do
diff --git a/spec/system/v2_lesson_project_submissions/like_spec.rb b/spec/system/v2_lesson_project_submissions/like_spec.rb
index 904573fb2f..1f010f5b7e 100644
--- a/spec/system/v2_lesson_project_submissions/like_spec.rb
+++ b/spec/system/v2_lesson_project_submissions/like_spec.rb
@@ -4,67 +4,32 @@
let(:user) { create(:user) }
let(:lesson) { create(:lesson, :project) }
- context "when liking other users' submissions" do
- before do
- Flipper.enable(:v2_project_submissions)
- create(:project_submission, lesson:)
+ before do
+ Flipper.enable(:v2_project_submissions)
+ create(:project_submission, lesson:)
- sign_in(user)
- visit lesson_path(lesson)
- end
-
- after do
- Flipper.disable(:v2_project_submissions)
- end
-
- it 'you can like another users submission' do
- within(:test_project_submission, 1) do
- expect(find(:test_id, 'like-count')).to have_content('0')
- find(:test_id, 'like-submission').click
- expect(find(:test_id, 'like-count')).to have_content('1')
- end
- end
-
- it 'you can unlike another users submission' do
- within(:test_project_submission, 1) do
- find(:test_id, 'like-submission').click
- expect(find(:test_id, 'like-count')).to have_content('1')
- find(:test_id, 'like-submission').click
- expect(find(:test_id, 'like-count')).to have_content('0')
- end
- end
+ sign_in(user)
+ visit lesson_path(lesson)
end
- context 'when liking your own submission' do
- before do
- Flipper.enable(:v2_project_submissions)
- create(:project_submission, lesson:, user:)
-
- sign_in(user)
- visit lesson_path(lesson)
- end
-
- after do
- Flipper.disable(:v2_project_submissions)
- end
+ after do
+ Flipper.disable(:v2_project_submissions)
+ end
- it 'you can like your submission' do
- within(:test_project_submission, 1) do |submission|
- expect(submission).to have_content(user.username)
- expect(find(:test_id, 'like-count')).to have_content('0')
- find(:test_id, 'like-submission').click
- expect(find(:test_id, 'like-count')).to have_content('1')
- end
+ it 'you can like another users submission' do
+ within(:test_project_submission, 1) do
+ expect(find(:test_id, 'like-count')).to have_content('0')
+ find(:test_id, 'like-submission').click
+ expect(find(:test_id, 'like-count')).to have_content('1')
end
+ end
- it 'you can unlike your submission' do
- within(:test_project_submission, 1) do |submission|
- expect(submission).to have_content(user.username)
- find(:test_id, 'like-submission').click
- expect(find(:test_id, 'like-count')).to have_content('1')
- find(:test_id, 'like-submission').click
- expect(find(:test_id, 'like-count')).to have_content('0')
- end
+ it 'you can unlike another users submission' do
+ within(:test_project_submission, 1) do
+ find(:test_id, 'like-submission').click
+ expect(find(:test_id, 'like-count')).to have_content('1')
+ find(:test_id, 'like-submission').click
+ expect(find(:test_id, 'like-count')).to have_content('0')
end
end
end
diff --git a/spec/system/v2_user_project_submissions/delete_submission_spec.rb b/spec/system/v2_user_project_submissions/delete_submission_spec.rb
new file mode 100644
index 0000000000..161033be2b
--- /dev/null
+++ b/spec/system/v2_user_project_submissions/delete_submission_spec.rb
@@ -0,0 +1,35 @@
+require 'rails_helper'
+
+RSpec.describe 'Deleting a Project Submission on the Dashboard' do
+ let(:user) { create(:user) }
+ let(:lesson) { create(:lesson, :project) }
+
+ before do
+ Flipper.enable(:v2_project_submissions)
+
+ create(:project_submission, user:, lesson:)
+ sign_in(user)
+ visit dashboard_path
+ end
+
+ after do
+ Flipper.disable(:v2_project_submissions)
+ end
+
+ it 'successfully deletes a submission' do
+ sleep 0.1 # it will not open the dropdown without this
+ within(:test_id, 'user-submissions-list') do
+ expect(page).to have_content(lesson.title)
+ end
+
+ find(:test_id, 'submission-action-menu-btn').click
+
+ page.accept_confirm do
+ find(:test_id, 'delete-submission').click
+ end
+
+ within(:test_id, 'user-submissions-list') do
+ expect(page).not_to have_content(lesson.title)
+ end
+ end
+end
diff --git a/spec/system/v2_user_project_submissions/edit_submission_spec.rb b/spec/system/v2_user_project_submissions/edit_submission_spec.rb
new file mode 100644
index 0000000000..061a0b5e59
--- /dev/null
+++ b/spec/system/v2_user_project_submissions/edit_submission_spec.rb
@@ -0,0 +1,66 @@
+require 'rails_helper'
+
+RSpec.describe 'Editing a Project Submission on the Dashboard' do
+ let(:user) { create(:user) }
+ let(:another_user) { create(:user) }
+ let(:lesson) { create(:lesson, :project) }
+ let(:edited_field_values) do
+ {
+ repo_url: 'https://github.com/edited-project-repo-url',
+ live_preview_url: 'http://edited-live-preview-url.com'
+ }
+ end
+
+ before do
+ Flipper.enable(:v2_project_submissions)
+
+ create(:project_submission, user:, lesson:)
+ sign_in(user)
+ visit dashboard_path
+ # sleep 2
+ end
+
+ after do
+ Flipper.disable(:v2_project_submissions)
+ end
+
+ it 'successfully edits a submission' do
+ sleep 0.1 # it will not open the dropdown without this
+ find(:test_id, 'submission-action-menu-btn').click
+ find(:test_id, 'edit-submission').click
+
+ Pages::ProjectSubmissions::Form.new(**edited_field_values).tap do |edit_form|
+ edit_form.fill_in
+ edit_form.submit
+ end
+
+ within(:test_id, 'submission-item') do
+ expect(page).to have_content(lesson.title)
+ expect(page.find(:test_id, 'view-code-btn')['href']).to eq('https://github.com/edited-project-repo-url')
+ expect(page.find(:test_id, 'live-preview-btn')['href']).to eq('http://edited-live-preview-url.com/')
+ end
+
+ # mark the submission as private
+
+ find(:test_id, 'submission-action-menu-btn').click
+ find(:test_id, 'edit-submission').click
+
+ Pages::ProjectSubmissions::Form.new.tap do |form|
+ form.v2_make_private
+ form.submit
+ end
+
+ within(:test_id, 'user-submissions-list') do
+ expect(page).to have_content(lesson.title)
+ end
+
+ using_session('another_user') do
+ sign_in(another_user)
+ visit lesson_path(lesson)
+
+ within(:test_id, 'submissions-list') do
+ expect(page).not_to have_content(user.username)
+ end
+ end
+ end
+end