Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7d82a21
Add repos table
codersquirrelbln Aug 26, 2024
9a6ee06
Bring repos into db
codersquirrelbln Aug 26, 2024
9ab9a4e
Add sidekiq and background job for syncing repos in database
codersquirrelbln Aug 27, 2024
db85230
Add application to stylesheet
codersquirrelbln Aug 27, 2024
b5e0857
Uncomment css_compressor in application config
codersquirrelbln Aug 27, 2024
2264e2a
Add link_directory JS to manifest
codersquirrelbln Aug 27, 2024
9f68d02
Fix migration files
codersquirrelbln Aug 30, 2024
277424e
Adjust ci pipeline -wip
codersquirrelbln Aug 30, 2024
e16b65e
Add eslint gem
codersquirrelbln Aug 30, 2024
40c1cae
Merge branch 'main' into create-repos-table
codersquirrelbln Aug 30, 2024
76856a6
Add repo sync service
codersquirrelbln Sep 5, 2024
7c65343
Improve repo fetching via api or db
codersquirrelbln Sep 6, 2024
399f4da
Update yarn integrity
codersquirrelbln Sep 7, 2024
4d00341
Adjust campaigns and repository associations and views
codersquirrelbln Sep 7, 2024
5c04162
fix user associations
codersquirrelbln Sep 7, 2024
af6cc08
Merge branch 'main' into create-repos-table
codersquirrelbln Sep 8, 2024
e1c469a
Remove yarn from ci pipeline
codersquirrelbln Sep 8, 2024
67a79ab
Merge branch 'main' into create-repos-table
codersquirrelbln Sep 8, 2024
4c98445
Fixing tests
codersquirrelbln Sep 21, 2024
ee7c51b
Adjust routes and slim down campaigns controller
codersquirrelbln Sep 21, 2024
e70a1f6
Refactor sync repos service
codersquirrelbln Sep 21, 2024
1b66d17
Remove json format in home controller and remove registrations contro…
codersquirrelbln Sep 21, 2024
4c47ba5
campaigns form WIP
codersquirrelbln Feb 8, 2025
a7cbf53
Debugging currencies format
codersquirrelbln Feb 9, 2025
50c4570
Merge branch 'main' into create-repos-table
codersquirrelbln Feb 9, 2025
3f579e6
Fix campaign show UX
codersquirrelbln Feb 9, 2025
cf13768
fix button select toggle
codersquirrelbln Feb 9, 2025
15c4109
Fix campaign edit currencies
codersquirrelbln Feb 9, 2025
3e0e2c6
Fix button bug
codersquirrelbln Feb 10, 2025
4fbac27
Fix tests
codersquirrelbln Feb 10, 2025
269ef38
Fix currencies update problem
codersquirrelbln Feb 19, 2025
bb21642
Fix accepted currencies update
codersquirrelbln Feb 22, 2025
b6b3011
Fix authentication for campaigns
codersquirrelbln Feb 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
92 changes: 61 additions & 31 deletions app/controllers/campaigns_controller.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# 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])
@repository = @campaign.repository
@accepted_currencies = if @campaign.accepted_currencies == 'all'
Campaign::ALL_CURRENCIES
else
@campaign.accepted_currencies.split(',')
@campaign.accepted_currencies
end
end

Expand All @@ -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
39 changes: 24 additions & 15 deletions app/controllers/contributions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

# <p id="wallet-address"><%= @sending_wallet.address if @user.wallet.present? %></p>
# <% unless @user.wallet.present? %>
# <%= button_tag "Add Wallet", type: "button", class: "text-blue-600 hover:text-blue-800", data: { action: "wallet#openConnectModal" } %>
# <% end %>
# </div>
# <% 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: [])
Expand Down
35 changes: 12 additions & 23 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.'
Expand Down
18 changes: 18 additions & 0 deletions app/controllers/repositories_controller.rb
Original file line number Diff line number Diff line change
@@ -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
6 changes: 4 additions & 2 deletions app/controllers/users/callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 0 additions & 15 deletions app/controllers/users/registrations_controller.rb

This file was deleted.

18 changes: 13 additions & 5 deletions app/javascript/controllers/currency_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand All @@ -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);
Expand All @@ -46,21 +52,23 @@ 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();
}

updateAcceptedCurrenciesField() {
this.acceptedCurrenciesTarget.value = this.selectedCurrencies.join(",");
console.log(this.selectedCurrencies);
}

updateSelectAllState() {
Expand Down
19 changes: 13 additions & 6 deletions app/models/campaign.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading