diff --git a/Gemfile.lock b/Gemfile.lock index bdde3b3..050db2b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -404,6 +404,7 @@ GEM rufus-scheduler (~> 3.2) sidekiq (>= 6, < 8) tilt (>= 1.4.0, < 3) + slop (3.6.0) smart_properties (1.17.0) snaky_hash (2.0.1) hashie diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb index 2f9d11e..8c6cc70 100644 --- a/app/controllers/campaigns_controller.rb +++ b/app/controllers/campaigns_controller.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true class CampaignsController < ApplicationController - before_action :set_repository, only: %i[new create edit] + before_action :authenticate_user!, only: %i[new create edit update] + before_action :set_repository, only: %i[new create edit update] before_action :check_repository_ownership!, only: %i[new create edit] - before_action :set_campaign, only: %i[edit update destroy] + before_action :set_campaign, only: %i[edit update] def show @campaign = Campaign.find(params[:id]) @@ -11,7 +12,7 @@ def show @accepted_currencies = if @campaign.accepted_currencies == 'all' Campaign::ALL_CURRENCIES else - @campaign.accepted_currencies.split(',') + @campaign.accepted_currencies end end @@ -24,65 +25,94 @@ def create @campaign = @repository.build_campaign(campaign_params) @campaign.receiving_wallet = current_user.wallet - respond_to do |format| - if @campaign.save - format.html { redirect_to user_repository_campaign_path(@repository.user, @repository, @campaign), notice: 'Campaign was successfully created.' } - format.json { render json: @campaign, status: :created } - else - log_errors(@campaign) - Rails.logger.error(@campaign.errors.full_messages.to_sentence) - format.html { render :new, alert: @campaign.errors.full_messages.join('. ') } - format.json { render json: { errors: @campaign.errors.full_messages }, status: :unprocessable_entity } - end + process_accepted_currencies(@campaign) + + if @campaign.save + redirect_to user_repository_campaign_path(current_user, @repository, @campaign), notice: 'Campaign was successfully created.' + else + flash.now[:alert] = @campaign.errors.full_messages.join('. ') + Rails.logger.debug "Campaign save failed. Errors: #{@campaign.errors.full_messages}" + render :new end end - def edit; end + def edit + @repo_name = @campaign.repository + @accepted_currencies = @campaign.accepted_currencies + end def update + process_accepted_currencies(@campaign) + if @campaign.update(campaign_params) - redirect_to user_repository_campaign_path(@repository.user, @repository, @campaign), notice: 'Campaign was successfully updated.' + redirect_to user_repository_campaign_path(@repository.user, @repository, @campaign), notice: 'Campaign updated successfully!' else + flash.now[:alert] = @campaign.errors.full_messages.join('. ') render :edit end end - def destroy - @campaign.destroy - redirect_to campaigns_url, notice: 'Campaign was successfully destroyed.' - end - private def set_campaign - @campaign = Campaign.find_by(id: params[:id]) - redirect_to root_path, alert: "Campaign not found with id: #{params[:id]}." unless @campaign + @campaign = current_user.campaigns.find(params[:id]) end def set_repository - @repository = Repository.find(params[:repository_id]) - redirect_to root_path, alert: 'Repository not found.' unless @repository + if action_name == 'new' || action_name == 'create' + @repository = current_user.repositories.find_by(id: params[:repository_id]) + + if @repository.nil? + redirect_to root_path, alert: 'Repository not found or does not belong to you.' + return + end + else + @campaign = Campaign.find_by(id: params[:id]) + if @campaign.nil? + redirect_to root_path, alert: "Campaign not found with id: #{params[:id]}." + return + end + @repository = @campaign.repository + end + + Rails.logger.debug "Repository set in #{action_name} action: #{@repository.inspect}" + end + + def find_wallet_for_repo_owner(repository) + owner = User.find_by(uid: repository.owner_login) + owner&.wallet end def check_repository_ownership! + Rails.logger.debug "Current user: #{current_user.inspect}" + Rails.logger.debug "Repository user: #{@repository.user.inspect}" return if current_user == @repository.user flash[:alert] = 'You are not authorized to create a campaign for this repository' redirect_to root_path end - def log_errors(campaign) - Rails.logger.debug campaign.errors.full_messages.to_sentence + def process_accepted_currencies(campaign) + currencies_param = params[:campaign][:accepted_currencies] + + return unless currencies_param.is_a?(String) + + logger.debug "Accepted currencies before processing: #{currencies_param}" + + processed_currencies = currencies_param.gsub(/[{}"]/, '').split(',').map(&:strip).reject(&:empty?) + + logger.debug "Accepted currencies after processing: #{processed_currencies}" + + campaign.accepted_currencies = processed_currencies end - def find_wallet_for_repo_owner(repository) - owner = User.find_by(uid: repository.owner_login) - owner&.wallet + def log_errors(campaign) + Rails.logger.debug campaign.errors.full_messages.to_sentence end def campaign_params - params.require(:campaign).permit(:title, :description, :repository_id, :receiving_wallet_id, :contribution_cadence).tap do |whitelisted| - whitelisted[:accepted_currencies] = params[:campaign][:accepted_currencies].split(',') if params[:campaign][:accepted_currencies].present? + params.require(:campaign).permit(:repository_id, :receiving_wallet_id, :title, :description, :contribution_cadence).tap do |whitelisted| + whitelisted[:accepted_currencies] = params[:campaign][:accepted_currencies].is_a?(String) ? params[:campaign][:accepted_currencies].split(',') : params[:campaign][:accepted_currencies] end end end diff --git a/app/controllers/contributions_controller.rb b/app/controllers/contributions_controller.rb index 3f8f0ed..40e6287 100644 --- a/app/controllers/contributions_controller.rb +++ b/app/controllers/contributions_controller.rb @@ -8,32 +8,41 @@ def new pp 'new action' @campaign = Campaign.find(params[:campaign_id]) pp '++++++++++++++++++++' + pp @campaign pp '++++++++++++++++++++' + @receiving_wallet = @campaign.receiving_wallet.address + @sending_wallet = current_user.wallet.address + @contribution = Contribution.new @accepted_currencies = @campaign.accepted_currencies.split(',') - end + # we need receiving wallet and sending wallet + # receiving is connected to campaign, owner of campaign has a wallet in db + # sending wallet is the current_user. what happens is this is your campaign? any different display? + # if this is your campaign, you should not be able to send funds, because that would be redundant and only cost gas + # if this is not your campaign, you should be able to send funds + # if this is your campaign, instead of contibute button could display a share this campaign button + # that would copy the url to the clipboard + +#
<%= @sending_wallet.address if @user.wallet.present? %>
+# <% unless @user.wallet.present? %> +# <%= button_tag "Add Wallet", type: "button", class: "text-blue-600 hover:text-blue-800", data: { action: "wallet#openConnectModal" } %> +# <% end %> +# +# <% end %> + end def create pp 'create contrib' - end + @receiving_wallet = @campaign.receiving_wallet_id + @sending_wallet = current_user.wallet_id - private + p @receiving_wallet + p @sending_wallet - def set_receiving_wallet - @campaign = Campaign.find(params[:campaign_id]) - pp @campaign - - @receiving_wallet = Wallet.find_by(id: @campaign.receiving_wallet_id) - pp @receiving_wallet - @receiving_wallet_address = @receiving_wallet&.address end - def set_user - pp 'set user in contrib' - @user = current_user - pp @user.wallet.address - end + private def contributions_params params.require(:contribution).permit(:contribution_cadence, :repo_identifier, :receiving_wallet_id, accepted_currencies: []) diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 107a121..27f65ff 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -5,16 +5,9 @@ class HomeController < ApplicationController def index fetch_user_data_from_database - prepare_campaigns_mapping - - if @github_user_data - respond_to do |format| - format.html - format.json { render_github_data_as_json } - end - else - handle_github_data_failure - end + # prepare_campaigns_mapping + + handle_github_data_failure unless @github_user_data end private @@ -28,21 +21,17 @@ def fetch_user_data_from_database @repositories = current_user.repositories.select(:id, :full_name, :name, :html_url, :description) end - def prepare_campaigns_mapping - repository_ids = @repositories.pluck(:id) + # def prepare_campaigns_mapping + # repository_ids = @repositories.pluck(:id) - campaigns = Campaign.where(repository_id: repository_ids) - @campaigns_by_repository_id = campaigns.index_by(&:repository_id) - logger.debug "Campaigns by Repo Identifier: #{@campaigns_by_repository_id.inspect}" - end + # campaigns = Campaign.where(repository_id: repository_ids) + # @campaigns_by_repository_id = campaigns.index_by(&:repository_id) + # logger.debug "Campaigns by Repo Identifier: #{@campaigns_by_repository_id.inspect}" - def render_github_data_as_json - render json: { - user: @github_user_data, - avatar: @avatar, - repositories: @repositories - } - end + # @respositories_with_campaigns = @repositories.map do |repository| + # { repository: repository, campaign: @campaigns_by_repository_id[repository.id] } + # end + # end def handle_github_data_failure flash[:alert] = 'Failed to retrieve GitHub data. Please try again later.' diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 86a204a..49ae4f7 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -1,6 +1,24 @@ # frozen_string_literal: true class RepositoriesController < ApplicationController + before_action :authenticate_user!, only: %i[index show] + def index + @repositories = current_user.repositories.includes(:campaigns) + # prepare_campaigns_mapping + end + + private + + def prepare_campaigns_mapping + repository_ids = @repositories.pluck(:id) + + campaigns = Campaign.where(repository_id: repository_ids) + @campaigns_by_repository_id = campaigns.index_by(&:repository_id) + logger.debug "Campaigns by Repo Identifier: #{@campaigns_by_repository_id.inspect}" + + @respositories_with_campaigns = @repositories.map do |repository| + { repository:, campaign: @campaigns_by_repository_id[repository.id] } + end end end diff --git a/app/controllers/users/callbacks_controller.rb b/app/controllers/users/callbacks_controller.rb index 118c383..2d5b2cf 100644 --- a/app/controllers/users/callbacks_controller.rb +++ b/app/controllers/users/callbacks_controller.rb @@ -10,10 +10,12 @@ def github Rails.logger.debug "User persisted: #{@user.inspect}" sign_in_and_redirect @user, event: :authentication set_flash_message(:notice, :success, kind: 'GitHub') if is_navigational_format? + SyncReposJob.perform_later(@user.id) else Rails.logger.debug "User could not be persisted: #{@user.errors.full_messages.join(', ')}" - session['devise.github_data'] = request.env['omniauth.auth'].except('extra') - redirect_to root_path + # session['devise.github_data'] = request.env['omniauth.auth'].except('extra') + flash[:alert] = 'Failed to sign in with GitHub. Please try again later.' + redirect_to new_user_session_path end end end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb deleted file mode 100644 index b701be7..0000000 --- a/app/controllers/users/registrations_controller.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module Users - class RegistrationsController < Devise::RegistrationsController - private - - def signup_params - params.require(:user).permit(:name, :email, :password, :password_confirmation) - end - - def account_update_params - params.require(:user).permit(:name, :email, :password, :password_confirmation, :current_password) - end - end -end diff --git a/app/javascript/controllers/currency_controller.js b/app/javascript/controllers/currency_controller.js index 4be38fe..93cc4e9 100644 --- a/app/javascript/controllers/currency_controller.js +++ b/app/javascript/controllers/currency_controller.js @@ -9,7 +9,10 @@ export default class extends Controller { ]; connect() { - this.selectedCurrencies = []; + this.selectedCurrencies = this.currencyButtonTargets + .filter((button) => button.classList.contains("bg-blue-500")) + .map((button) => button.dataset.currencyValue); + this.updateAcceptedCurrenciesField(); this.updateSelectAllState(); } @@ -21,8 +24,11 @@ export default class extends Controller { button.classList.toggle("bg-blue-500"); button.classList.toggle("text-white"); + button.classList.toggle("bg-white"); + button.classList.toggle("text-black"); const isSelected = button.classList.contains("bg-blue-500"); + if (isSelected) { if (!this.selectedCurrencies.includes(currency)) { this.selectedCurrencies.push(currency); @@ -46,14 +52,15 @@ export default class extends Controller { this.currencyButtonTargets.forEach((button) => { button.classList.toggle("bg-blue-500", isChecked); button.classList.toggle("text-white", isChecked); + button.classList.toggle("bg-white", !isChecked); + button.classList.toggle("text-black", !isChecked); const currency = button.dataset.currencyValue; if (isChecked && !this.selectedCurrencies.includes(currency)) { this.selectedCurrencies.push(currency); } else if (!isChecked) { - const index = this.selectedCurrencies.indexOf(currency); - if (index !== -1) { - this.selectedCurrencies.splice(index, 1); - } + this.selectedCurrencies = this.selectedCurrencies.filter( + (c) => c !== currency + ); } }); this.updateAcceptedCurrenciesField(); @@ -61,6 +68,7 @@ export default class extends Controller { updateAcceptedCurrenciesField() { this.acceptedCurrenciesTarget.value = this.selectedCurrencies.join(","); + console.log(this.selectedCurrencies); } updateSelectAllState() { diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 74f4b3c..62cc9cc 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -7,14 +7,21 @@ class Campaign < ApplicationRecord # Validations validates :title, presence: { message: 'must be provided and cannot be blank.' } - validates :description, presence: { message: 'must be provided and cannot be blank.' } - validates :accepted_currencies, length: { minimum: 1, message: 'must include at least one currency.' } + validates :accepted_currencies, length: { minimum: 1, message: 'must include at least one currency.' }, if: -> { accepted_currencies.present? } + validates :repository_id, uniqueness: { message: 'A campaign for this repository already exists' } # Constants ALL_CURRENCIES = %w[USDC BTC ETH].freeze - # Optional association indicator for UI logic or elsewhere - # def repo_centric? - # repo_identifier.present? - # end + private + + def process_accepted_currencies + currencies_param = params[:campaign][:accepted_currencies] + + return unless currencies_param.is_a?(String) + + processed_currencies = currencies_param.gsub(/[{}"]/, '').split(',').map(&:strip).reject(&:empty?) + + params[:campaign][:accepted_currencies] = processed_currencies + end end diff --git a/app/services/sync_repos_service.rb b/app/services/sync_repos_service.rb index b00e866..e48ab82 100644 --- a/app/services/sync_repos_service.rb +++ b/app/services/sync_repos_service.rb @@ -14,7 +14,7 @@ def call Rails.logger.debug "GitHub API Response: #{response.code} - #{response.body}" repositories_data.each do |repository_data| - repository = Repository.find_or_create_by(repo_github_id: repository_data['id']) do |r| + repository = Repository.find_or_initialize_by(repo_github_id: repository_data['id']).tap do |r| r.user = @user r.name = repository_data['name'] r.full_name = repository_data['full_name'] @@ -28,23 +28,7 @@ def call r.pushed_to_github_at = repository_data['pushed_at'] end - Rails.logger.debug "Repository synced: #{repository.full_name}" - - next unless repository.persisted? && repository.changed? - - repository.update( - name: repository_data['name'], - full_name: repository_data['full_name'], - owner_login: repository_data['owner']['login'], - html_url: repository_data['html_url'], - description: repository_data['description'], - private: repository_data['private'], - fork: repository_data['fork'], - created_on_github_at: repository_data['created_at'], - updated_on_github_at: repository_data['updated_at'], - pushed_to_github_at: repository_data['pushed_at'] - ) - Rails.logger.debug "Repository updated and synced: #{repository.full_name}" + repository.save! end else Rails.logger.error "GitHub API Request failed: #{response.code} - #{response.message}" diff --git a/app/views/campaigns/_form.html.erb b/app/views/campaigns/_form.html.erb index e9ecb8b..2114313 100644 --- a/app/views/campaigns/_form.html.erb +++ b/app/views/campaigns/_form.html.erb @@ -1,7 +1,15 @@- <%= "#{current_user.nickname}, project owner of #{@repository.name}, verified" %> + <%= "#{current_user.nickname}, project owner of #{@repository.full_name}, verified" %> <%= image_tag("verified-icon.svg", alt: "Verified Checkmark", class: "inline-block align-middle", style: "height: 20px; width: 20px;") %>
- <%= @campaign.receiving_wallet.address %> -
-> -
- <% else %> - <%= button_tag "Add Wallet", type: "button", class: "text-blue-600 hover:text-blue-800 mb-4", data: { action: "wallet#openConnectModal" } %> - <% end %> -|
- <%= link_to repo.full_name, "https://github.com/#{repo.full_name}", target: "_blank", rel: "noopener noreferrer", class: "text-blue-600 hover:text-blue-800" %>
+ <%= link_to repository.full_name, "https://github.com/#{repository.full_name}", target: "_blank", rel: "noopener noreferrer", class: "text-blue-600 hover:text-blue-800" %>
- <% campaign = @campaigns_by_repository_id[repo.id] %>
- <% if campaign %>
- <%= link_to 'Show Campaign', edit_user_repository_campaign_path(current_user, repo, campaign), class: "btn btn-success" %>
+ <% if repository.campaign %>
+ <%= link_to 'Show Campaign', user_repository_campaign_path(current_user, repository, repository.campaign), class: "btn btn-success" %>
<% else %>
- <%= link_to 'Create Campaign', new_user_repository_campaign_path(current_user, repo), class: "bg-blue-500 text-white px-4 py-2 rounded inline-block" %>
+ <%= link_to 'Create Campaign', new_user_repository_campaign_path(current_user, repository), class: "bg-blue-500 text-white px-4 py-2 rounded inline-block" %>
<% end %>
|
- | |