diff --git a/app/assets/javascripts/lib/pulltorefresh.js b/app/assets/javascripts/lib/pulltorefresh.js index e79ecdd10..e6fe9f0bd 100644 --- a/app/assets/javascripts/lib/pulltorefresh.js +++ b/app/assets/javascripts/lib/pulltorefresh.js @@ -41,7 +41,7 @@ onRefresh: () => { return window.location.reload(); }, - resistanceFunction: t => { + resistanceFunction: (t) => { return Math.min(1, t / 2.5); }, shouldPullToRefresh: () => { @@ -50,7 +50,7 @@ (document.getElementById('articles-list') || document.getElementById('user-dashboard') || document.getElementById('article-body') || - document.getElementById('classifieds-index-container')) && + document.getElementById('listings-index-container')) && !document.body.classList.contains('modal-open') ); }, @@ -178,7 +178,7 @@ function onTouchStart(e) { // here, we must pick a handler first, and then append their html/css on the DOM - var target = shared.handlers.filter(h => { + var target = shared.handlers.filter((h) => { return h.contains(e.target); })[0]; @@ -347,7 +347,7 @@ var handler = {}; // merge options with defaults - Object.keys(defaults).forEach(key => { + Object.keys(defaults).forEach((key) => { handler[key] = options[key] || defaults[key]; }); @@ -358,7 +358,7 @@ : defaults.refreshTimeout; // normalize elements - methods.forEach(method => { + methods.forEach((method) => { if (typeof handler[method] === 'string') { handler[method] = document.querySelector(handler[method]); } @@ -369,7 +369,7 @@ shared.events = setupEvents(); } - handler.contains = target => { + handler.contains = (target) => { return handler.triggerElement.contains(target); }; @@ -395,7 +395,7 @@ shared.events = null; } - shared.handlers.forEach(h => { + shared.handlers.forEach((h) => { h.destroy(); }); }, diff --git a/app/assets/stylesheets/classified_listings.scss b/app/assets/stylesheets/listings.scss similarity index 94% rename from app/assets/stylesheets/classified_listings.scss rename to app/assets/stylesheets/listings.scss index 8c7a3c17f..9d8aa911d 100644 --- a/app/assets/stylesheets/classified_listings.scss +++ b/app/assets/stylesheets/listings.scss @@ -1,12 +1,12 @@ @import 'variables'; @import 'mixins'; -.classifieds-container { +.listings-container { margin: 24px 0; text-align: left; max-width: 100%; min-height: 100vh; - .classified-filters { + .listing-filters { padding: 0 16px; a { padding: 3px 16px; @@ -23,11 +23,11 @@ margin: 0px 4px; } } - .classified-filters-categories { + .listing-filters-categories { a { display: block; padding: 7px 16px; - &.classified-create-link { + &.listing-create-link { border: 2px solid darken($green, 14%); color: darken($green, 19%); padding: 6px 16px; @@ -42,13 +42,13 @@ min-width: 50px; text-align: center; padding: 3px 16px; - &.classified-create-link { + &.listing-create-link { padding: 2px 16px; } } } } - .classified-filters-tags { + .listing-filters-tags { padding: 20px 0px; position: relative; input { @@ -69,7 +69,7 @@ margin-right: 8px; } } - .classified-search-clear { + .listing-search-clear { background: $light-gray; border: 1px solid $light-medium-gray; position: absolute; @@ -80,7 +80,7 @@ left: 282px; } } - .classified-tag { + .listing-tag { font-size: 0.7em; color: $black; border-radius: 100px; @@ -107,7 +107,7 @@ } } } - .classifieds-columns { + .listings-columns { display: grid; grid-gap: 24px; padding: 0 16px; @@ -133,13 +133,13 @@ border-top-left-radius: 8px; border-top-right-radius: 8px; } - .classified-form-inner { + .listing-form-inner { padding: 0px 15px 40px; @media screen and (min-width: 580px) { padding: 0px 15px 18px; } } - .listings-back-button { + .listing-back-button { font-size: 0.8em; margin: 2px 0px 8px; display: block; @@ -149,7 +149,7 @@ color: var(--accent-brand); margin: 0px; } - .classified-errors { + .listing-errors { background: $red; color: $black; padding: 20px; @@ -261,7 +261,7 @@ font-size: 1.1em; } } - .classified-listings-unpublish { + .listings-unpublish { background: $red; } p { @@ -269,7 +269,7 @@ color: var(--card-color-tertiary); } } - .classifieds-load-more-button { + .listings-load-more-button { text-align: center; button { @@ -342,7 +342,7 @@ font-weight: bold; } -.single-classified-listing-container { +.single-listing-container { width: 100%; z-index: 20; position: fixed; @@ -352,7 +352,7 @@ bottom: 0px; margin: 12px auto 0px; overflow: hidden; - .single-classified-listing-container__inner { + .single-listing-container__inner { position: absolute; height: 100%; width: 100%; @@ -367,17 +367,17 @@ right: 0; box-sizing: border-box; } - .single-classified-listing-container__spacer { + .single-listing-container__spacer { height: 150px; margin-bottom: 150px; } } - .single-classified-listing-container__inner::-webkit-scrollbar { + .single-listing-container__inner::-webkit-scrollbar { display: none; } } -.single-classified-listing { +.single-listing { width: 100%; display: inline-block; border: 1px solid $light-medium-gray; @@ -452,10 +452,10 @@ background-color: #f1f1f1; } } - .single-classified-listing-body { + .single-listing-body { padding: 10px 12px; font-size: 15px; - .classified-listing-contact-cta { + .listing-contact-cta { border: 2px solid $black; color: $black; padding: 8px 10px; @@ -466,7 +466,7 @@ width: 80%; } } - .single-classified-listing-tags { + .single-listing-tags { padding: 10px 15px; a { color: var(--card-color-tertiary); @@ -483,19 +483,19 @@ font-weight: bold; } } - .single-classified-listing-author-info { + .single-listing-author-info { font-size: 0.69em; color: var(--card-color-tertiary); padding: 0px 15px 4px; a { color: var(--card-color-tertiary); display: inline-block; - &.classified-listing-edit-button { + &.listing-edit-button { margin-left: 4px; } } } - &.single-classified-listing--opened { + &.single-listing--opened { z-index: 20; display: block; position: relative; @@ -508,13 +508,13 @@ h3 { font-size: calc(20px + 0.05vw); } - .single-classified-listing-body { + .single-listing-body { font-size: calc(18px + 0.05vw); } } } } -.single-classified-listing-info-link { +.single-listing-info-link { display: block; width: 320px; max-width: 92%; @@ -566,7 +566,7 @@ form.listings-contact-via-connect { } } -.classified-listings-modal-background { +.listings-modal-background { z-index: 15; position: fixed; left: 0; diff --git a/app/assets/stylesheets/ltags/LiquidTags.scss b/app/assets/stylesheets/ltags/LiquidTags.scss index e7794c477..1cb633022 100644 --- a/app/assets/stylesheets/ltags/LiquidTags.scss +++ b/app/assets/stylesheets/ltags/LiquidTags.scss @@ -11,6 +11,6 @@ @import 'GistTag'; @import 'GithubReadmeTag'; @import 'PollTag'; -@import 'ClassifiedListingTag'; +@import 'ListingTag'; @import 'StackexchangeTag'; @import 'WikipediaTag'; diff --git a/app/assets/stylesheets/ltags/ClassifiedListingTag.scss b/app/assets/stylesheets/ltags/ListingTag.scss similarity index 100% rename from app/assets/stylesheets/ltags/ClassifiedListingTag.scss rename to app/assets/stylesheets/ltags/ListingTag.scss diff --git a/app/assets/stylesheets/minimal.scss b/app/assets/stylesheets/minimal.scss index 0fc90decb..5f5955583 100644 --- a/app/assets/stylesheets/minimal.scss +++ b/app/assets/stylesheets/minimal.scss @@ -27,7 +27,7 @@ @import 'sticky-nav'; @import 'sidebar-data'; @import 'video-collection'; -@import 'classified_listings'; +@import 'listings'; @import 'credits'; @import 'item-list'; @import 'color-picker'; diff --git a/app/controllers/admin/classified_listing_categories_controller.rb b/app/controllers/admin/listing_categories_controller.rb similarity index 95% rename from app/controllers/admin/classified_listing_categories_controller.rb rename to app/controllers/admin/listing_categories_controller.rb index d9b3b0ecd..04164fa12 100644 --- a/app/controllers/admin/classified_listing_categories_controller.rb +++ b/app/controllers/admin/listing_categories_controller.rb @@ -1,5 +1,5 @@ module Admin - class ClassifiedListingCategoriesController < Admin::ApplicationController + class ListingCategoriesController < Admin::ApplicationController # Overwrite any of the RESTful controller actions to implement custom behavior # For example, you may want to send an email after a foo is updated. # diff --git a/app/controllers/api/v0/classified_listings_controller.rb b/app/controllers/api/v0/listings_controller.rb similarity index 53% rename from app/controllers/api/v0/classified_listings_controller.rb rename to app/controllers/api/v0/listings_controller.rb index 6e6957ab4..aedcdd63d 100644 --- a/app/controllers/api/v0/classified_listings_controller.rb +++ b/app/controllers/api/v0/listings_controller.rb @@ -1,48 +1,46 @@ module Api module V0 - class ClassifiedListingsController < ApiController + class ListingsController < ApiController include Pundit - include ClassifiedListingsToolkit + include ListingsToolkit before_action :authenticate_with_api_key_or_current_user!, only: %i[create update] before_action :authenticate_with_api_key_or_current_user, only: %i[show] - before_action :set_classified_listing, only: %i[update] + before_action :set_listing, only: %i[update] before_action :set_cache_control_headers, only: %i[index show] skip_before_action :verify_authenticity_token, only: %i[create update] def index - @classified_listings = ClassifiedListing.published. + @listings = Listing.published. select(ATTRIBUTES_FOR_SERIALIZATION). - includes(:user, :organization, :taggings, :classified_listing_category) + includes(:user, :organization, :taggings, :listing_category) if params[:category].present? - category = ClassifiedListingCategory.find_by(slug: params[:category]) - @classified_listings = - @classified_listings.where(classified_listing_category: category) + @listings = @listings.in_category(params[:category]) end - @classified_listings = @classified_listings.order(bumped_at: :desc) + @listings = @listings.order(bumped_at: :desc) per_page = (params[:per_page] || 30).to_i num = [per_page, 100].min page = params[:page] || 1 - @classified_listings = @classified_listings.page(page).per(num) + @listings = @listings.page(page).per(num) - set_surrogate_key_header ClassifiedListing.table_key, @classified_listings.map(&:record_key) + set_surrogate_key_header Listing.table_key, @listings.map(&:record_key) end def show - relation = ClassifiedListing.published + relation = Listing.published # if the user is authenticated we allow them to access # their own unpublished listings as well - relation = relation.union(@user.classified_listings) if @user + relation = relation.union(@user.listings) if @user - @classified_listing = relation.select(ATTRIBUTES_FOR_SERIALIZATION).find(params[:id]) + @listing = relation.select(ATTRIBUTES_FOR_SERIALIZATION).find(params[:id]) - set_surrogate_key_header @classified_listing.record_key + set_surrogate_key_header @listing.record_key end def create @@ -53,6 +51,8 @@ module Api super end + # Note: since this is used for selecting from the DB, we need to use the + # actual column name for the listing category, prefixed with classified_. ATTRIBUTES_FOR_SERIALIZATION = %i[ id user_id organization_id title slug body_markdown cached_tag_list classified_listing_category_id processed_html published @@ -75,7 +75,7 @@ module Api end def process_unsuccessful_draft - render json: { errors: @classified_listing.errors }, status: :unprocessable_entity + render json: { errors: @listing.errors }, status: :unprocessable_entity end def process_successful_creation @@ -83,7 +83,7 @@ module Api end def process_unsuccessful_creation - render json: { errors: @classified_listing.errors }, status: :unprocessable_entity + render json: { errors: @listing.errors }, status: :unprocessable_entity end alias process_unsuccessful_update process_unsuccessful_creation @@ -95,6 +95,23 @@ module Api def process_after_unpublish render "show", status: :ok end + + # Note: when doing the big listings refactoring we decided not to break + # this API. Since other code assumes the params will be under listing, + # we're copying them over. + def listing_params + params["listing"] = params["classified_listing"] + if (category_id = find_category_id(params.dig("listing", "category"))) + params["listing"]["listing_category_id"] = category_id + end + super + end + + def find_category_id(slug) + return if slug.blank? + + ListingCategory.select(:id).find_by(slug: slug)&.id + end end end end diff --git a/app/controllers/chat_channels_controller.rb b/app/controllers/chat_channels_controller.rb index 1780212bf..78e7ad65c 100644 --- a/app/controllers/chat_channels_controller.rb +++ b/app/controllers/chat_channels_controller.rb @@ -86,7 +86,7 @@ class ChatChannelsController < ApplicationController def create_chat chat_recipient = User.find(params[:user_id]) - valid_listing = ClassifiedListing.where(user_id: params[:user_id], contact_via_connect: true).limit(1) + valid_listing = Listing.where(user_id: params[:user_id], contact_via_connect: true).limit(1) authorize ChatChannel if chat_recipient.inbox_type == "open" || valid_listing.length == 1 diff --git a/app/controllers/concerns/classified_listings_toolkit.rb b/app/controllers/concerns/listings_toolkit.rb similarity index 66% rename from app/controllers/concerns/classified_listings_toolkit.rb rename to app/controllers/concerns/listings_toolkit.rb index 69268a382..5bf869b98 100644 --- a/app/controllers/concerns/classified_listings_toolkit.rb +++ b/app/controllers/concerns/listings_toolkit.rb @@ -1,56 +1,56 @@ -module ClassifiedListingsToolkit +module ListingsToolkit extend ActiveSupport::Concern MANDATORY_FIELDS_FOR_UPDATE = %i[body_markdown title tag_list].freeze def unpublish_listing - @classified_listing.update(published: false) + @listing.update(published: false) end def publish_listing - @classified_listing.update(published: true) + @listing.update(published: true) end def update_listing_details # [thepracticaldev/oss] Not entirely sure what the intention behind the # original code was, but at least this is more compact. filtered_params = listing_params.reject { |_k, v| v.nil? } - @classified_listing.update(filtered_params) + @listing.update(filtered_params) end def bump_listing_success - @classified_listing.update(bumped_at: Time.current) + @listing.update(bumped_at: Time.current) end def clear_listings_cache - ClassifiedListings::BustCacheWorker.perform_async(@classified_listing.id) + Listings::BustCacheWorker.perform_async(@listing.id) end - def set_classified_listing - @classified_listing = ClassifiedListing.find(params[:id]) + def set_listing + @listing = Listing.find(params[:id]) end def create - @classified_listing = ClassifiedListing.new(listing_params) + @listing = Listing.new(listing_params) # this will 401 for now if they don't belong in the org - authorize @classified_listing, :authorized_organization_poster? if @classified_listing.organization_id.present? + authorize @listing, :authorized_organization_poster? if @listing.organization_id.present? - @classified_listing.user_id = current_user.id - org = Organization.find_by(id: @classified_listing.organization_id) + @listing.user_id = current_user.id + org = Organization.find_by(id: @listing.organization_id) if listing_params[:action] == "draft" create_draft return end - unless @classified_listing.valid? + unless @listing.valid? @credits = current_user.credits.unspent process_unsuccessful_creation return end - cost = @classified_listing.cost + cost = @listing.cost # we use the org's credits if available, otherwise we default to the user's if org&.enough_credits?(cost) create_listing(org, cost) @@ -62,26 +62,26 @@ module ClassifiedListingsToolkit end ALLOWED_PARAMS = %i[ - title body_markdown classified_listing_category_id tag_list + title body_markdown listing_category_id tag_list expires_at contact_via_connect location organization_id action ].freeze # Filter for a set of known safe params def listing_params - tags = params["classified_listing"].delete("tags") + tags = params["listing"].delete("tags") if tags.present? - params["classified_listing"]["tag_list"] = tags.join(", ") + params["listing"]["tag_list"] = tags.join(", ") end - params.require(:classified_listing).permit(ALLOWED_PARAMS) + params.require(:listing).permit(ALLOWED_PARAMS) end def create_draft - @classified_listing.published = false - if @classified_listing.save + @listing.published = false + if @listing.save process_successful_draft else @credits = current_user.credits.unspent - @classified_listing.cached_tag_list = listing_params[:tag_list] + @listing.cached_tag_list = listing_params[:tag_list] @organizations = current_user.organizations process_unsuccessful_draft end @@ -93,18 +93,18 @@ module ClassifiedListingsToolkit # subtract credits Credits::Buyer.call( purchaser: purchaser, - purchase: @classified_listing, + purchase: @listing, cost: cost, ) # save the listing - @classified_listing.bumped_at = Time.current - @classified_listing.published = true + @listing.bumped_at = Time.current + @listing.published = true # since we can't raise active record errors in this transaction # due to the fact that we need to display them in the :new view, # we manually rollback the transaction if there are validation errors - raise ActiveRecord::Rollback unless @classified_listing.save + raise ActiveRecord::Rollback unless @listing.save successful_transaction = true end @@ -115,16 +115,16 @@ module ClassifiedListingsToolkit process_successful_creation else @credits = current_user.credits.unspent - @classified_listing.cached_tag_list = listing_params[:tag_list] + @listing.cached_tag_list = listing_params[:tag_list] @organizations = current_user.organizations process_unsuccessful_creation end end def update - authorize @classified_listing + authorize @listing - cost = @classified_listing.cost + cost = @listing.cost # NOTE: this should probably be split in three different actions: bump, unpublish, publish return bump_listing(cost) if listing_params[:action] == "bump" @@ -134,7 +134,7 @@ module ClassifiedListingsToolkit process_after_unpublish return elsif listing_params[:action] == "publish" - unless @classified_listing.bumped_at? + unless @listing.bumped_at? first_publish(cost) return end @@ -150,7 +150,7 @@ module ClassifiedListingsToolkit end def bump_listing(cost) - org = Organization.find_by(id: @classified_listing.organization_id) + org = Organization.find_by(id: @listing.organization_id) if org&.enough_credits?(cost) charge_credits_before_bump(org, cost) @@ -165,7 +165,7 @@ module ClassifiedListingsToolkit ActiveRecord::Base.transaction do Credits::Buyer.call( purchaser: purchaser, - purchase: @classified_listing, + purchase: @listing, cost: cost, ) @@ -174,14 +174,14 @@ module ClassifiedListingsToolkit end def first_publish(cost) - available_author_credits = @classified_listing.author.credits.unspent + available_author_credits = @listing.author.credits.unspent available_user_credits = [] - if @classified_listing.author.is_a?(Organization) + if @listing.author.is_a?(Organization) available_user_credits = current_user.credits.unspent end if available_author_credits.size >= cost - create_listing(@classified_listing.author, cost) + create_listing(@listing.author, cost) elsif available_user_credits.size >= cost create_listing(current_user, cost) else @@ -190,7 +190,7 @@ module ClassifiedListingsToolkit end def listing_updatable? - at_least_one_param_present? && (bumped_in_last_24_hrs? || !@classified_listing.published) + at_least_one_param_present? && (bumped_in_last_24_hrs? || !@listing.published) end def at_least_one_param_present? @@ -198,6 +198,6 @@ module ClassifiedListingsToolkit end def bumped_in_last_24_hrs? - @classified_listing.bumped_at && @classified_listing.bumped_at > 24.hours.ago + @listing.bumped_at && @listing.bumped_at > 24.hours.ago end end diff --git a/app/controllers/internal/buffer_updates_controller.rb b/app/controllers/internal/buffer_updates_controller.rb index dedfcc25c..5e946bf54 100644 --- a/app/controllers/internal/buffer_updates_controller.rb +++ b/app/controllers/internal/buffer_updates_controller.rb @@ -5,7 +5,7 @@ class Internal::BufferUpdatesController < Internal::ApplicationController fb_post = params[:fb_post] tweet = params[:tweet] listing_id = params[:listing_id] - listing = ClassifiedListing.find(params[:listing_id]) if listing_id.present? + listing = Listing.find(params[:listing_id]) if listing_id.present? article&.update(featured: true) case params[:social_channel] when "main_twitter" diff --git a/app/controllers/internal/classified_listings_controller.rb b/app/controllers/internal/classified_listings_controller.rb deleted file mode 100644 index 0a4b0bbb0..000000000 --- a/app/controllers/internal/classified_listings_controller.rb +++ /dev/null @@ -1,54 +0,0 @@ -class Internal::ClassifiedListingsController < Internal::ApplicationController - include ClassifiedListingsToolkit - layout "internal" - - def index - @classified_listings = - ClassifiedListing.includes(%i[user classified_listing_category]). - page(params[:page]).order("bumped_at DESC").per(50) - - @classified_listings = @classified_listings.published unless include_unpublished? - @classified_listings = @classified_listings.in_category(params[:filter]) if params[:filter].present? - end - - def edit - @classified_listing = ClassifiedListing.find(params[:id]) - end - - def update - @classified_listing = ClassifiedListing.find(params[:id]) - handle_publish_status if listing_params[:published] - bump_listing(@classified_listing.cost) if listing_params[:action] == "bump" - update_listing_details - clear_listings_cache - flash[:success] = "Listing updated successfully" - redirect_to edit_internal_classified_listing_path(@classified_listing) - end - - def destroy - @classified_listing = ClassifiedListing.find(params[:id]) - @classified_listing.destroy - flash[:warning] = "'#{@classified_listing.title}' was destroyed successfully" - redirect_to internal_classified_listings_path - end - - private - - ALLOWED_PARAMS = %i[ - published body_markdown title category classified_listing_category_id tag_list action - ].freeze - private_constant :ALLOWED_PARAMS - - def listing_params - params.require(:classified_listing).permit(ALLOWED_PARAMS) - end - - def handle_publish_status - unpublish_listing if listing_params[:published] == "0" - publish_listing if listing_params[:published] == "1" - end - - def include_unpublished? - params[:include_unpublished] == "1" - end -end diff --git a/app/controllers/internal/listings_controller.rb b/app/controllers/internal/listings_controller.rb new file mode 100644 index 000000000..4df8cb2a3 --- /dev/null +++ b/app/controllers/internal/listings_controller.rb @@ -0,0 +1,54 @@ +class Internal::ListingsController < Internal::ApplicationController + include ListingsToolkit + layout "internal" + + def index + @listings = + Listing.includes(%i[user listing_category]). + page(params[:page]).order("bumped_at DESC").per(50) + + @listings = @listings.published unless include_unpublished? + @listings = @listings.in_category(params[:filter]) if params[:filter].present? + end + + def edit + @listing = Listing.find(params[:id]) + end + + def update + @listing = Listing.find(params[:id]) + handle_publish_status if listing_params[:published] + bump_listing(@listing.cost) if listing_params[:action] == "bump" + update_listing_details + clear_listings_cache + flash[:success] = "Listing updated successfully" + redirect_to edit_internal_listing_path(@listing) + end + + def destroy + @listing = Listing.find(params[:id]) + @listing.destroy + flash[:warning] = "'#{@listing.title}' was destroyed successfully" + redirect_to internal_listings_path + end + + private + + ALLOWED_PARAMS = %i[ + published body_markdown title category listing_category_id tag_list action + ].freeze + private_constant :ALLOWED_PARAMS + + def listing_params + params.require(:listing).permit(ALLOWED_PARAMS) + end + + def handle_publish_status + unpublish_listing if listing_params[:published] == "0" + publish_listing if listing_params[:published] == "1" + end + + def include_unpublished? + params[:include_unpublished] == "1" + end +end diff --git a/app/controllers/classified_listings_controller.rb b/app/controllers/listings_controller.rb similarity index 67% rename from app/controllers/classified_listings_controller.rb rename to app/controllers/listings_controller.rb index b9d4953d8..fa7dc1095 100644 --- a/app/controllers/classified_listings_controller.rb +++ b/app/controllers/listings_controller.rb @@ -1,5 +1,5 @@ -class ClassifiedListingsController < ApplicationController - include ClassifiedListingsToolkit +class ListingsController < ApplicationController + include ListingsToolkit before_action :check_limit, only: [:create] JSON_OPTIONS = { @@ -11,39 +11,40 @@ class ClassifiedListingsController < ApplicationController } }.freeze - before_action :set_classified_listing, only: %i[edit update destroy] + before_action :set_listing, only: %i[edit update destroy] before_action :set_cache_control_headers, only: %i[index] before_action :raise_suspended, only: %i[new create update] - after_action :verify_authorized, only: %i[edit update] before_action :authenticate_user!, only: %i[edit update new dashboard] + after_action :verify_authorized, only: %i[edit update] def index - published_listings = ClassifiedListing.where(published: true) - @displayed_classified_listing = published_listings.find_by(slug: params[:slug]) if params[:slug] + published_listings = Listing.where(published: true) + @displayed_listing = published_listings.find_by(slug: params[:slug]) if params[:slug] if params[:view] == "moderate" - not_found unless @displayed_classified_listing - return redirect_to edit_internal_listing_path(id: @displayed_classified_listing.id) + not_found unless @displayed_listing + return redirect_to edit_internal_listing_path(id: @displayed_listing.id) end - @classified_listings = + @listings = if params[:category].blank? published_listings. order("bumped_at DESC"). includes(:user, :organization, :taggings). limit(12) else - ClassifiedListing.none + Listing.none end - @listings_json = @classified_listings.to_json(JSON_OPTIONS) - @displayed_listing_json = @displayed_classified_listing.to_json(JSON_OPTIONS) + @listings_json = @listings.to_json(JSON_OPTIONS) + @displayed_listing_json = @displayed_listing.to_json(JSON_OPTIONS) + # TODO: [mkohl] Can we change this to listings-#{params[:category]}? set_surrogate_key_header "classified-listings-#{params[:category]}" end def new - @classified_listing = ClassifiedListing.new + @listing = Listing.new @organizations = current_user.organizations @credits = current_user.credits.unspent end @@ -57,32 +58,32 @@ class ClassifiedListingsController < ApplicationController end def edit - authorize @classified_listing + authorize @listing @organizations = current_user.organizations @credits = current_user.credits.unspent end def dashboard - @classified_listings = current_user.classified_listings. + @listings = current_user.listings. includes(:organization, :taggings) organizations_ids = current_user.organization_memberships. where(type_of_user: "admin"). pluck(:organization_id) @orgs = Organization.where(id: organizations_ids) - @org_listings = ClassifiedListing.where(organization_id: organizations_ids) + @org_listings = Listing.where(organization_id: organizations_ids) @user_credits = current_user.unspent_credits_count end def delete_confirm - @classified_listing = ClassifiedListing.find_by(slug: params[:slug]) - not_found unless @classified_listing - authorize @classified_listing + @listing = Listing.find_by(slug: params[:slug]) + not_found unless @listing + authorize @listing end def destroy - authorize @classified_listing - @classified_listing.destroy! + authorize @listing + @listing.destroy! redirect_to "/listings/dashboard", notice: "Listing was successfully deleted." end @@ -101,7 +102,7 @@ class ClassifiedListingsController < ApplicationController end def process_successful_creation - redirect_to classified_listings_path + redirect_to listings_path end def process_unsuccessful_creation diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index eb30c0b00..7aeac8ff0 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -1,11 +1,11 @@ class SearchController < ApplicationController before_action :authenticate_user!, only: %i[tags chat_channels reactions] before_action :format_integer_params - before_action :sanitize_params, only: %i[classified_listings reactions feed_content] + before_action :sanitize_params, only: %i[listings reactions feed_content] - CLASSIFIED_LISTINGS_PARAMS = [ + LISTINGS_PARAMS = [ :category, - :classified_listing_search, + :listing_search, :page, :per_page, :tag_boolean_mode, @@ -65,9 +65,9 @@ class SearchController < ApplicationController render json: { result: ccm_docs } end - def classified_listings - cl_docs = Search::ClassifiedListing.search_documents( - params: classified_listing_params.to_h, + def listings + cl_docs = Search::Listing.search_documents( + params: listing_params.to_h, ) render json: { result: cl_docs } @@ -125,8 +125,8 @@ class SearchController < ApplicationController params.permit(accessible) end - def classified_listing_params - params.permit(CLASSIFIED_LISTINGS_PARAMS) + def listing_params + params.permit(LISTINGS_PARAMS) end def user_params diff --git a/app/controllers/social_previews_controller.rb b/app/controllers/social_previews_controller.rb index fc25d074e..a0d94009a 100644 --- a/app/controllers/social_previews_controller.rb +++ b/app/controllers/social_previews_controller.rb @@ -26,7 +26,7 @@ class SocialPreviewsController < ApplicationController end def listing - @listing = ClassifiedListing.find(params[:id]).decorate + @listing = Listing.find(params[:id]).decorate set_respond end diff --git a/app/controllers/stories_controller.rb b/app/controllers/stories_controller.rb index 7db08083d..988acef7f 100644 --- a/app/controllers/stories_controller.rb +++ b/app/controllers/stories_controller.rb @@ -4,7 +4,7 @@ class StoriesController < ApplicationController title path id user_id comments_count public_reactions_count organization_id reading_time video_thumbnail_url video video_duration_in_minutes language experience_level_rating experience_level_rating_distribution cached_user cached_organization - classified_listing_category_id + listing_category_id ], methods: %i[ readable_publish_date cached_tag_list_array flare_tag class_name @@ -157,7 +157,7 @@ class StoriesController < ApplicationController assign_feed_stories assign_hero_html assign_podcasts - assign_classified_listings + assign_listings get_latest_campaign_articles if SiteConfig.campaign_sidebar_enabled? @article_index = true @featured_story = (featured_story || Article.new)&.decorate @@ -338,8 +338,8 @@ class StoriesController < ApplicationController select(:slug, :title, :podcast_id, :image) end - def assign_classified_listings - @classified_listings = ClassifiedListing.where(published: true).select(:title, :classified_listing_category_id, :slug, :bumped_at) + def assign_listings + @listings = Listing.where(published: true).select(:title, :classified_listing_category_id, :slug, :bumped_at) end def redirect_to_lowercase_username diff --git a/app/dashboards/dashboard_manifest.rb b/app/dashboards/dashboard_manifest.rb index 1b419b0f8..aa25438f0 100644 --- a/app/dashboards/dashboard_manifest.rb +++ b/app/dashboards/dashboard_manifest.rb @@ -29,7 +29,7 @@ class DashboardManifest html_variant_trials html_variant_successes sponsorships - classified_listing_categories + listing_categories ].freeze # DASHBOARDS = [ # :users, diff --git a/app/dashboards/classified_listing_category_dashboard.rb b/app/dashboards/listing_category_dashboard.rb similarity index 85% rename from app/dashboards/classified_listing_category_dashboard.rb rename to app/dashboards/listing_category_dashboard.rb index 4f2d81e7e..e060e7528 100644 --- a/app/dashboards/classified_listing_category_dashboard.rb +++ b/app/dashboards/listing_category_dashboard.rb @@ -1,6 +1,6 @@ require "administrate/base_dashboard" -class ClassifiedListingCategoryDashboard < Administrate::BaseDashboard +class ListingCategoryDashboard < Administrate::BaseDashboard # ATTRIBUTE_TYPES # a hash that describes the type of each of the model's fields. # @@ -8,7 +8,7 @@ class ClassifiedListingCategoryDashboard < Administrate::BaseDashboard # which determines how the attribute is displayed # on pages throughout the dashboard. ATTRIBUTE_TYPES = { - classified_listings: Field::HasMany, + listings: Field::HasMany, id: Field::Number, cost: Field::Number, created_at: Field::DateTime, @@ -72,10 +72,10 @@ class ClassifiedListingCategoryDashboard < Administrate::BaseDashboard # }.freeze COLLECTION_FILTERS = {}.freeze - # Overwrite this method to customize how classified listing categories are displayed + # Overwrite this method to customize how listing categories are displayed # across all pages of the admin dashboard. # - # def display_resource(classified_listing_category) - # "ClassifiedListingCategory ##{classified_listing_category.id}" + # def display_resource(listing_category) + # "ListingCategory ##{listing_category.id}" # end end diff --git a/app/decorators/classified_listing_decorator.rb b/app/decorators/listing_decorator.rb similarity index 66% rename from app/decorators/classified_listing_decorator.rb rename to app/decorators/listing_decorator.rb index 983c84f77..90409d75c 100644 --- a/app/decorators/classified_listing_decorator.rb +++ b/app/decorators/listing_decorator.rb @@ -1,13 +1,13 @@ -class ClassifiedListingDecorator < ApplicationDecorator +class ListingDecorator < ApplicationDecorator DEFAULT_COLOR = "#000000".freeze def social_preview_category - category = object.classified_listing_category + category = object.listing_category category.social_preview_description.presence || category.name end def social_preview_color(brightness: 1.0) - category = object.classified_listing_category + category = object.listing_category color = category.social_preview_color.presence || DEFAULT_COLOR HexComparer.new([color]).brightness(brightness) end diff --git a/app/helpers/classified_listing_helper.rb b/app/helpers/listing_helper.rb similarity index 58% rename from app/helpers/classified_listing_helper.rb rename to app/helpers/listing_helper.rb index 4be490d94..d3ed365a1 100644 --- a/app/helpers/classified_listing_helper.rb +++ b/app/helpers/listing_helper.rb @@ -1,18 +1,18 @@ -module ClassifiedListingHelper +module ListingHelper def select_options_for_categories - ClassifiedListingCategory.select(:id, :name, :cost).map do |cl| + ListingCategory.select(:id, :name, :cost).map do |cl| ["#{cl.name} (#{cl.cost} #{'Credit'.pluralize(cl.cost)})", cl.id] end end def categories_for_display - ClassifiedListingCategory.pluck(:slug, :name).map do |slug, name| + ListingCategory.pluck(:slug, :name).map do |slug, name| { slug: slug, name: name } end end def categories_available - ClassifiedListingCategory.all.each_with_object({}) do |cat, h| + ListingCategory.all.each_with_object({}) do |cat, h| h[cat.slug] = cat.attributes.slice("cost", "name", "rules") end.deep_symbolize_keys end diff --git a/app/javascript/article-form/__tests__/__snapshots__/articleForm.test.jsx.snap b/app/javascript/article-form/__tests__/__snapshots__/articleForm.test.jsx.snap index 7f0ca6a2a..6533d8224 100644 --- a/app/javascript/article-form/__tests__/__snapshots__/articleForm.test.jsx.snap +++ b/app/javascript/article-form/__tests__/__snapshots__/articleForm.test.jsx.snap @@ -34,7 +34,7 @@ exports[` renders properly 1`] = ` autoComplete="off" class="articleform__tags" id="tag-input" - name="classified_listing[tag_list]" + name="listing[tag_list]" onBlur={[Function]} onFocus={[Function]} onInput={[Function]} diff --git a/app/javascript/article-form/elements/__tests__/__snapshots__/tags.test.jsx.snap b/app/javascript/article-form/elements/__tests__/__snapshots__/tags.test.jsx.snap index 2535d16b0..e10bc459c 100644 --- a/app/javascript/article-form/elements/__tests__/__snapshots__/tags.test.jsx.snap +++ b/app/javascript/article-form/elements/__tests__/__snapshots__/tags.test.jsx.snap @@ -19,7 +19,7 @@ exports[` renders properly 1`] = ` autoComplete="off" class="articleform__tags" id="tag-input" - name="classified_listing[tag_list]" + name="listing[tag_list]" onBlur={[Function]} onFocus={[Function]} onInput={[Function]} diff --git a/app/javascript/listings/__tests__/ClassifiedFilterTags.test.jsx b/app/javascript/listings/__tests__/ClassifiedFilterTags.test.jsx index b29d9ac60..83959cb80 100644 --- a/app/javascript/listings/__tests__/ClassifiedFilterTags.test.jsx +++ b/app/javascript/listings/__tests__/ClassifiedFilterTags.test.jsx @@ -1,8 +1,8 @@ import { h } from 'preact'; import { deep } from 'preact-render-spy'; -import ClassifiedFiltersTags from '../components/ClassifiedFiltersTags'; +import ListingFiltersTags from '../components/ListingFiltersTags'; -describe('', () => { +describe('', () => { const firstTag = { id: 1, tag: 'clojure', @@ -36,11 +36,11 @@ describe('', () => { tags: getTags(), }); - const renderClassifiedFilterTags = (props = getProps()) => - deep(); + const renderListingFilterTags = (props = getProps()) => + deep(); describe('Should render a search field', () => { - const context = renderClassifiedFilterTags(); + const context = renderListingFilterTags(); const searchField = context.find('#listings-search'); it('Should have "search" as placeholder', () => { @@ -57,7 +57,7 @@ describe('', () => { }); describe('', () => { - const context = renderClassifiedFilterTags(); + const context = renderListingFilterTags(); it('Should render the clear query button', () => { expect(context.find('#clear-query-button').exists()).toBe(true); @@ -65,7 +65,7 @@ describe('', () => { it('Should not render the clear query button', () => { const propsWithoutQuery = { ...getProps(), query: '' }; - const contextWithAnotherProps = renderClassifiedFilterTags( + const contextWithAnotherProps = renderListingFilterTags( propsWithoutQuery, ); @@ -76,7 +76,7 @@ describe('', () => { }); it('Should render the selected Tags', () => { - const context = renderClassifiedFilterTags(); + const context = renderListingFilterTags(); getTags().forEach((tag) => { const selectedTag = context.find(`#selected-tag-${tag.id}`); diff --git a/app/javascript/listings/__tests__/ClassifiedFilters.test.jsx b/app/javascript/listings/__tests__/ClassifiedFilters.test.jsx index f4a11db2b..ceb1494b2 100644 --- a/app/javascript/listings/__tests__/ClassifiedFilters.test.jsx +++ b/app/javascript/listings/__tests__/ClassifiedFilters.test.jsx @@ -1,8 +1,8 @@ import { h } from 'preact'; import render from 'preact-render-to-json'; -import ClassifiedFilters from '../components/ClassifiedFilters'; +import ListingFilters from '../components/ListingFilters'; -describe('', () => { +describe('', () => { const firstTag = { id: 1, tag: 'clojure', @@ -61,11 +61,11 @@ describe('', () => { tags: getTags(), }); - const renderClassifiedFilters = (props = getProps()) => - render(); + const renderListingFilters = (props = getProps()) => + render(); it('Should match the snapshot', () => { - const context = renderClassifiedFilters(); + const context = renderListingFilters(); expect(context).toMatchSnapshot(); }); }); diff --git a/app/javascript/listings/__tests__/ClassifiedFiltersCategories.test.jsx b/app/javascript/listings/__tests__/ClassifiedFiltersCategories.test.jsx index ce6b908cb..02df34200 100644 --- a/app/javascript/listings/__tests__/ClassifiedFiltersCategories.test.jsx +++ b/app/javascript/listings/__tests__/ClassifiedFiltersCategories.test.jsx @@ -1,8 +1,8 @@ import { h } from 'preact'; import { deep } from 'preact-render-spy'; -import ClassifiedFiltersCategories from '../components/ClassifiedFiltersCategories'; +import ListingFiltersCategories from '../components/ListingFiltersCategories'; -describe('', () => { +describe('', () => { const firstCategory = { id: 20, slug: 'clojure', @@ -31,11 +31,11 @@ describe('', () => { }, }); - const renderClassifiedFilterCategories = (props = getProps()) => - deep(); + const renderListingFilterCategories = (props = getProps()) => + deep(); describe('Should render the links to allow navigation', () => { - const context = renderClassifiedFilterCategories(); + const context = renderListingFilterCategories(); it('Should render a link and a message relative to listings', () => { const listingsLink = context.find('#listings-link'); @@ -47,7 +47,7 @@ describe('', () => { it('When there\'s no category, the className of the listings link should be "selected"', () => { const propsWithoutCategory = { ...getProps(), category: '' }; - const contextWithoutCategory = renderClassifiedFilterCategories( + const contextWithoutCategory = renderListingFilterCategories( propsWithoutCategory, ); @@ -59,7 +59,7 @@ describe('', () => { const newListingLink = context.find('#listings-new-link'); expect(newListingLink.attr('href')).toBe('/listings/new'); - expect(newListingLink.attr('className')).toBe('classified-create-link'); + expect(newListingLink.attr('className')).toBe('listing-create-link'); expect(newListingLink.text()).toBe('Create a Listing'); }); @@ -67,13 +67,13 @@ describe('', () => { const dashboardLink = context.find('#listings-dashboard-link'); expect(dashboardLink.attr('href')).toBe('/listings/dashboard'); - expect(dashboardLink.attr('className')).toBe('classified-create-link'); + expect(dashboardLink.attr('className')).toBe('listing-create-link'); expect(dashboardLink.text()).toBe('Manage Listings'); }); }); describe('Should render categories links', () => { - const context = renderClassifiedFilterCategories(); + const context = renderListingFilterCategories(); it('Should render the categories name and their respective links', () => { categories.forEach((category) => { const categoryLink = context.find(`#category-link-${category.id}`); diff --git a/app/javascript/listings/__tests__/ListingDashboard.test.jsx b/app/javascript/listings/__tests__/ListingDashboard.test.jsx index 4c2fcc4d7..2d723f601 100644 --- a/app/javascript/listings/__tests__/ListingDashboard.test.jsx +++ b/app/javascript/listings/__tests__/ListingDashboard.test.jsx @@ -58,7 +58,7 @@ const l = [ }, }, ]; -global.document.body.innerHTML = `
', () => { isOpen={false} />, ); - expect(context.find('.single-classified-listing').exists()).toBeTruthy(); + expect(context.find('.single-listing').exists()).toBeTruthy(); it('for listing title', () => { expect( context - .find('.single-classified-listing-header') + .find('.single-listing-header') .at(0) .childAt(0) .childAt(0) @@ -73,35 +73,26 @@ describe('', () => { }); it('for listing tags', () => { - expect( - context.find('.single-classified-listing-tags').childAt(0).text(), - ).toEqual(listing.tags[0]); + expect(context.find('.single-listing-tags').childAt(0).text()).toEqual( + listing.tags[0], + ); }); it('for listing category', () => { expect( - context - .find('.single-classified-listing-author-info') - .childAt(0) - .text(), + context.find('.single-listing-author-info').childAt(0).text(), ).toEqual(listing.category); }); it('for listing location', () => { expect( - context - .find('.single-classified-listing-author-info') - .childAt(1) - .text(), + context.find('.single-listing-author-info').childAt(1).text(), ).toEqual(`・${listing.location}`); }); it('for listing author', () => { expect( - context - .find('.single-classified-listing-author-info') - .childAt(3) - .text(), + context.find('.single-listing-author-info').childAt(3).text(), ).toEqual(listing.author.name); }); }); diff --git a/app/javascript/listings/__tests__/__snapshots__/AllListings.test.jsx.snap b/app/javascript/listings/__tests__/__snapshots__/AllListings.test.jsx.snap index 63bef9f16..44b7fab2e 100644 --- a/app/javascript/listings/__tests__/__snapshots__/AllListings.test.jsx.snap +++ b/app/javascript/listings/__tests__/__snapshots__/AllListings.test.jsx.snap @@ -2,18 +2,18 @@ exports[` Should render all listings 1`] = `
Eius et ullam. Dolores et qui. Quis qui omnis.

@@ -267,7 +267,7 @@ exports[` Should render all listings 1`] = ` } />
Should match the snapshot 1`] = ` class="listingform__input listingform__bodymarkdown" id="body_markdown" maxLength="400" - name="classified_listing[body_markdown]" + name="listing[body_markdown]" onInput={[Function]} placeholder="400 characters max, 12 line break max, no images allowed, *markdown is encouraged*" /> diff --git a/app/javascript/listings/__tests__/__snapshots__/ClassifiedFilters.test.jsx.snap b/app/javascript/listings/__tests__/__snapshots__/ClassifiedFilters.test.jsx.snap index 35dbd7d36..8c74518d5 100644 --- a/app/javascript/listings/__tests__/__snapshots__/ClassifiedFilters.test.jsx.snap +++ b/app/javascript/listings/__tests__/__snapshots__/ClassifiedFilters.test.jsx.snap @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` Should match the snapshot 1`] = ` +exports[` Should match the snapshot 1`] = `
Should match the snapshot 1`] = ` type="text" />
Should match the snapshot 1`] = ` Should match the snapshot 1`] = ` Should match the snapshot 1`] = `