Listings set custom expiry date (#3770)

* add expire_on column to classified_listings

* add expire_on to valid listing params

* add expire_on to model

* add expire date to new listing form

* add field in edit form

* add expiry dates to dashboard

* update expiry date in listing toolkit

* WIP unpublish job and test

test still has to run properly

* add job to class name

* change job to rake task

* revert snap change

* delete migration file

will add new one and revert schema changes to rename column

* reset schema

* add new migration to schema 'expires_at'

* change expire_on to expires_at
This commit is contained in:
Mario See 2019-08-23 17:33:50 -04:00 committed by Ben Halpern
parent 352a09e82f
commit 47c2885810
11 changed files with 74 additions and 5 deletions

View file

@ -158,7 +158,7 @@ class ClassifiedListingsController < ApplicationController
# Never trust parameters from the scary internet, only allow a specific list through.
def listing_params
accessible = %i[title body_markdown category tag_list contact_via_connect location organization_id action]
accessible = %i[title body_markdown category tag_list expires_at contact_via_connect location organization_id action]
params.require(:classified_listing).permit(accessible)
end
end

View file

@ -19,6 +19,7 @@ module ClassifiedListingsToolkit
@classified_listing.tag_list = listing_params[:tag_list] if listing_params[:tag_list]
@classified_listing.category = listing_params[:category] if listing_params[:category]
@classified_listing.location = listing_params[:location] if listing_params[:location]
@classified_listing.expires_at = listing_params[:expires_at] if listing_params[:expires_at]
@classified_listing.contact_via_connect = listing_params[:contact_via_connect] if listing_params[:contact_via_connect]
@classified_listing.save
end

View file

@ -26,6 +26,18 @@ export const ListingRow = ({ listing }) => {
''
);
const expiryDate = listing.expires_at ?
new Date(listing.expires_at.toString()).toLocaleDateString('default', {
day: '2-digit',
month: 'short',
}) : '' ;
const listingExpiry = expiryDate !== '' ? (
` | Expires on: ${expiryDate}`
) : (
''
);
return (
<div className={`dashboard-listing-row ${listing.published ? '' : 'expired'}`}>
{orgName}
@ -34,6 +46,7 @@ export const ListingRow = ({ listing }) => {
</a>
<span className="dashboard-listing-date">
{listingDate}
{listingExpiry}
{listingLocation}
</span>
<span className="dashboard-listing-category">

View file

@ -0,0 +1,34 @@
import PropTypes from 'prop-types';
import { h } from 'preact';
const ExpireDate = ({ onChange, defaultValue }) => {
let tomorrow = new Date();
let monthFromToday = new Date();
tomorrow.setDate(new Date().getDate() + 1);
tomorrow = tomorrow.toISOString().split('T')[0];
monthFromToday.setDate(new Date().getDate() + 30);
monthFromToday = monthFromToday.toISOString().split('T')[0];
return (
<div className="field">
<label className="listingform__label" htmlFor="expires_at">Custom Expire Date (if applicable for time sensitive events, deadlines, etc.)</label>
<input
type="date"
className="listingform__input"
id="expires_at"
name="classified_listing[expires_at]"
value={defaultValue}
onInput={onChange}
min={tomorrow}
max={monthFromToday}
/>
</div>
);
}
ExpireDate.propTypes = {
onChange: PropTypes.func.isRequired,
defaultValue: PropTypes.string.isRequired,
}
export default ExpireDate;

View file

@ -5,6 +5,7 @@ import BodyMarkdown from './elements/bodyMarkdown';
import Categories from './elements/categories';
import Tags from './elements/tags';
import OrgSettings from './elements/orgSettings';
import ExpireDate from './elements/expireDate';
export default class ListingForm extends Component {
constructor(props) {
@ -28,6 +29,7 @@ export default class ListingForm extends Component {
categoriesForDetails: this.categoriesForDetails,
organizations,
organizationId: null, // change this for /edit later
expireDate: this.listing.expires_at || '',
};
}
@ -47,6 +49,7 @@ export default class ListingForm extends Component {
categoriesForSelect,
organizations,
organizationId,
expireDate,
} = this.state;
const orgArea =
organizations && organizations.length > 0 ? (
@ -77,6 +80,7 @@ export default class ListingForm extends Component {
category={category}
onInput={linkState(this, 'tagList')}
/>
<ExpireDate defaultValue={expireDate} onChange={linkState(this, 'expireDate')} />
{orgArea}
{/* add contact via connect checkbox later */}
</div>

View file

@ -24,7 +24,7 @@ class ClassifiedListing < ApplicationRecord
validate :validate_category
algoliasearch per_environment: true do
attribute :title, :processed_html, :bumped_at, :tag_list, :category, :id, :user_id, :slug, :contact_via_connect, :location
attribute :title, :processed_html, :bumped_at, :tag_list, :category, :id, :user_id, :slug, :contact_via_connect, :location, :expires_at
attribute :author do
{ username: author.username,
name: author.name,

View file

@ -1,12 +1,12 @@
<div id="classifieds-listings-dashboard" data-listings="<%= @classified_listings.to_json(
only: %i[title tag_list created_at bumped_at updated_at category id user_id slug organization_id location published],
only: %i[title tag_list created_at expires_at bumped_at updated_at category id user_id slug organization_id location published],
include: {
author: { only: %i[username name], methods: %i[username profile_image_90] },
},
)%>" data-usercredits="<%= @user_credits %>"
data-orglistings="<%= @org_listings.to_json(
only: %i[title tag_list created_at bumped_at updated_at category id user_id slug organization_id location published],
only: %i[title tag_list created_at expires_at bumped_at updated_at category id user_id slug organization_id location published],
include: {
author: { only: %i[username name], methods: %i[username profile_image_90] },
},

View file

@ -42,6 +42,10 @@
<%= f.label "location", "Location" %>
<%= f.text_field "location", maxlength: 32, placeholder: "32 characters max, plain text" %>
</div>
<div class="field">
<%= f.label "expires_at", "Custom Expire Date" %>
<%= f.date_field "expires_at", min: Date.tomorrow, max: @classified_listing.bumped_at + 30.days %>
</div>
<div class="field">
<%= f.label "contact_via_connect", "Allow Users to Message Me Via In-App Chat (DEV Connect)" %>
<%= f.check_box "contact_via_connect" %>

View file

@ -0,0 +1,5 @@
class AddExpiresAtToClassifiedListings < ActiveRecord::Migration[5.2]
def change
add_column :classified_listings, :expires_at, :datetime
end
end

View file

@ -12,7 +12,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_08_18_191954) do
ActiveRecord::Schema.define(version: 2019_08_22_162434) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -254,6 +254,7 @@ ActiveRecord::Schema.define(version: 2019_08_18_191954) do
t.string "category"
t.boolean "contact_via_connect", default: false
t.datetime "created_at", null: false
t.datetime "expires_at"
t.datetime "last_buffered"
t.string "location"
t.bigint "organization_id"

View file

@ -34,6 +34,13 @@ task expire_old_listings: :environment do
end
end
task expire_old_listings: :environment do
ClassifiedListing.where("expires_at = ?", Time.zone.today).each do |listing|
listing.update(published: false)
listing.remove_from_index!
end
end
task clear_memory_if_too_high: :environment do
Rails.cache.clear if Rails.cache.stats.flatten[1]["bytes"].to_i > 9_650_000_000
end