Skip to content

Commit

Permalink
Admin partners page improvements (#7140)
Browse files Browse the repository at this point in the history
* Import stylesheet

* Add admin component, add width variable

* Adjust adverts perk width + add track slugs

* Add track slugs col

* Add TrackSlugselector, Save values in a hidden field

* Set up default values

* Correctly type multiselect ref, permit track_slugs

* Clarify comment

* Remove logging

* Tiny visual adjustments (#7142)

* Optimise
  • Loading branch information
dem4ron authored Nov 8, 2024
1 parent 1fcb484 commit 3a2cdaa
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 9 deletions.
2 changes: 1 addition & 1 deletion app/controllers/admin/adverts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ def use_advert

# Only allow a list of trusted parameters through.
def advert_params
params.require(:partner_advert).permit(*%i[status url markdown mailer_text light_logo dark_logo])
params.require(:partner_advert).permit!
end
end
23 changes: 23 additions & 0 deletions app/css/components/admin.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
body.namespace-admin.controller-partners.action-show,
body.namespace-admin.controller-perks.action-show,
body.namespace-admin.controller-adverts.action-show {
.c-perk-a {
width: var(--c-perk-a-width);
}

.c-perk-status-tag {
@apply border-1 px-2 py-[1px] rounded-5;
&.active {
@apply border-[#22c55e] text-[#22c55e];
}
&.retired {
@apply border-[#3b82f6] text-[#3b82f6];
}
&.pending {
@apply border-[#facc15] text-[#facc15];
}
&.out_of_budget {
@apply border-[#ef4444] text-[#ef4444];
}
}
}
1 change: 1 addition & 0 deletions app/css/defaults.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ body {
* https://base64.guru/converter/encode/image/svg
* */
--hex-bg-image: url("data:image/svg+xml;base64,PHN2ZyBpZD0ncGF0dGVybklkJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnPjxkZWZzPjxwYXR0ZXJuIGlkPSdhJyBwYXR0ZXJuVW5pdHM9J3VzZXJTcGFjZU9uVXNlJyB3aWR0aD0nMjknIGhlaWdodD0nNTAuMTE1JyBwYXR0ZXJuVHJhbnNmb3JtPSdzY2FsZSgyKSByb3RhdGUoMCknPjxyZWN0IHg9JzAnIHk9JzAnIHdpZHRoPScxMDAlJyBoZWlnaHQ9JzEwMCUnIGZpbGw9J2hzbGEoMCwwJSwxMDAlLDEpJy8+PHBhdGggZD0nTTE0LjQ5OCAxNi44NThMMCA4LjQ4OC4wMDItOC4yNTdsMTQuNS04LjM3NEwyOS04LjI2bC0uMDAyIDE2Ljc0NXptMCA1MC4wNkwwIDU4LjU0OGwuMDAyLTE2Ljc0NSAxNC41LTguMzczTDI5IDQxLjhsLS4wMDIgMTYuNzQ0ek0yOC45OTYgNDEuOGwtMTQuNDk4LTguMzcuMDAyLTE2Ljc0NEwyOSA4LjMxMmwxNC40OTggOC4zNy0uMDAyIDE2Ljc0NXptLTI5IDBsLTE0LjQ5OC04LjM3LjAwMi0xNi43NDRMMCA4LjMxMmwxNC40OTggOC4zNy0uMDAyIDE2Ljc0NXonICBzdHJva2Utd2lkdGg9JzAuNScgc3Ryb2tlPSdoc2xhKDI1OSwgMCUsIDkwJSwgMSknIGZpbGw9J25vbmUnLz48L3BhdHRlcm4+PC9kZWZzPjxyZWN0IHdpZHRoPSc4MDAlJyBoZWlnaHQ9JzgwMCUnIHRyYW5zZm9ybT0ndHJhbnNsYXRlKC0zOCwtNi40NiknIGZpbGw9J3VybCgjYSknLz48L3N2Zz4K");
--c-perk-a-width: 325px;
}
@media screen and (prefers-reduced-motion: reduce) {
body {
Expand Down
1 change: 1 addition & 0 deletions app/css/packs/admin.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

@import "../pages/admin/page";
@import "../pages/admin/table";
@import "../components/admin";
2 changes: 1 addition & 1 deletion app/css/pages/exercise-show.css
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,6 @@ body.namespace-tracks.controller-exercises.action-show {
.c-perk-a {
@apply absolute top-20;
right: var(--container-padding-x);
@apply w-[325px];
width: var(--c-perk-a-width);
}
}
11 changes: 11 additions & 0 deletions app/helpers/react_components/common/track_slugs_multiselector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module ReactComponents
module Common
class TrackSlugsMultiselector < ReactComponent
initialize_with :track_slugs, :selected_track_slugs

def to_s
super("common-track-slugs-multiselector", { track_slugs:, selected_track_slugs: })
end
end
end
end
117 changes: 117 additions & 0 deletions app/javascript/components/common/TrackSlugsMultiselector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useEffect, useRef } from 'react'
import { SelectInstance, GroupBase } from 'react-select'
import CreatableSelect from 'react-select/creatable'

type OptionType = {
label: string
value: string
}

export default function TrackSlugsMultiselector({
trackSlugs,
selectedTrackSlugs,
}: {
trackSlugs: string[]
selectedTrackSlugs: string // comes as a JSON array
}): JSX.Element {
const trackSlugsHiddenInputRef = useRef<HTMLInputElement | null>(null)
const selectRef =
useRef<SelectInstance<OptionType, true, GroupBase<OptionType>>>(null)

useEffect(() => {
trackSlugsHiddenInputRef.current = document.querySelector(
'#partner_advert_track_slugs'
) as HTMLInputElement

if (trackSlugsHiddenInputRef.current) {
trackSlugsHiddenInputRef.current.value =
JSON.stringify(selectedTrackSlugs)
}
}, [selectedTrackSlugs])

// Removes the annoying blue box-shadow on the embedded input
const handleFocus = () => {
if (selectRef.current) {
const input = selectRef.current.inputRef

if (input) {
input.style.boxShadow = 'none'
}
}
}

return (
<CreatableSelect
isMulti
ref={selectRef}
defaultValue={formatTags(JSON.parse(selectedTrackSlugs))}
options={formatTags(trackSlugs)}
isClearable={false}
maxMenuHeight={100}
onFocus={handleFocus}
styles={{
valueContainer: (base) => ({
...base,
padding: '8px',
}),

indicatorSeparator: (base) => ({
...base,
display: 'none',
'&:focus': {
border: 'none',
outline: 'none',
},
}),
indicatorsContainer: (base) => ({
...base,
display: 'none',
border: 'none',
'&:focus': {
border: 'none',
outline: 'none',
},
}),

multiValue: (base) => ({
...base,
borderRadius: '8px',
overflow: 'hidden',
backgroundColor: 'var(--backgroundColorI)',
border: '1px solid',
borderColor: '#2E57E8',
margin: '4px',
}),
multiValueLabel: (base) => ({
...base,
fontSize: '16px',
padding: '4px',
paddingLeft: '8px',
}),
multiValueRemove: (base) => ({
...base,
paddingRight: '8px',
color: 'var(--textColor6)',
'&:hover': {
background: '#E27979',
color: 'var(--textColor1)',
},
}),
}}
onChange={(selected): void => {
if (trackSlugsHiddenInputRef.current) {
trackSlugsHiddenInputRef.current.value = JSON.stringify(
selected.map((s) => s.value)
)
}
}}
/>
)
}

function formatTags(tags: string[]) {
return tags.map((tag) => ({
label: tag,
value: tag,
}))
}
11 changes: 11 additions & 0 deletions app/javascript/packs/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ const SiteUpdatesList = lazy(
const CopyToClipboardButton = lazy(
() => import('@/components/common/CopyToClipboardButton')
)
const TrackSlugsMultiselector = lazy(
() => import('@/components/common/TrackSlugsMultiselector')
)
const ThemeToggleButton = lazy(
() => import('@/components/common/ThemeToggleButton')
)
Expand Down Expand Up @@ -574,6 +577,14 @@ export const mappings = {
<CopyToClipboardButton textToCopy={data.text_to_copy} />
</Suspense>
),
'common-track-slugs-multiselector': (data: any): JSX.Element => (
<Suspense fallback={RenderLoader()}>
<TrackSlugsMultiselector
trackSlugs={data.track_slugs}
selectedTrackSlugs={data.selected_track_slugs}
/>
</Suspense>
),
'common-theme-toggle-button': (
data: Omit<ThemeToggleButtonProps, 'defaultTheme'> & {
default_theme: string
Expand Down
5 changes: 5 additions & 0 deletions app/views/admin/adverts/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
= f.label :dark_logo, class: 'text-h6 mb-4'
= f.file_field :dark_logo

.flex.flex-col.mb-16
= f.label :track_slugs, "Select Tracks", class: 'text-h6 mb-4'
= render ReactComponents::Common::TrackSlugsMultiselector.new(Track.pluck(:slug), advert.track_slugs)
= f.hidden_field :track_slugs, id: 'partner_advert_track_slugs'

%div
= f.submit class: 'btn btn-primary btn-base'

3 changes: 3 additions & 0 deletions app/views/admin/adverts/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
- require_stylesheet "about"
- require_stylesheet "admin"
.c-admin-page
.lg-container
%h1.text-h1.mb-16 Advert #{@partner.name}##{@advert.id}
= render ViewComponents::Partner::Advert.new(advert: @advert, preview: true)
%hr.my-32.border-borderColor5

.text-h6.mb-8 Status: #{@advert.status.titleize}
.text-h6.mb-8 Track slugs: #{@advert.track_slugs}
.text-h6.mb-8 URL: #{@advert.url}
.text-h6.mb-8 Num Impressions: #{@advert.num_impressions}
.text-h6.mb-8 Num Clicks: #{@advert.num_clicks}
Expand Down
10 changes: 8 additions & 2 deletions app/views/admin/partners/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- require_stylesheet "about"
- require_stylesheet "admin"
.py-20
.lg-container
%h1.text-h1= @partner.name
Expand All @@ -15,7 +17,8 @@
%tr
%td
%div{ class: 'max-w-[443px]' }= render ViewComponents::Partner::Perk.new(perk)
%td.w-arbitary= perk.status.titleize
%td.w-arbitary
%span{ class: "c-perk-status-tag #{perk.status}" }= perk.status.titleize
%td.w-arbitary= perk.num_clicks
%td.w-arbitary= link_to "Details", admin_partner_perk_path(@partner, perk)
%td.w-arbitary= link_to "Edit", edit_admin_partner_perk_path(@partner, perk)
Expand All @@ -29,13 +32,16 @@
%tr
%th Advert
%th Status
%th Track Slugs
%th Impressions
%th Clicks
%th{ colspan: 2 }
- @partner.adverts.each do |advert|
%tr
%td= render ViewComponents::Partner::Advert.new(advert:, preview: true)
%td.w-arbitary= advert.status.titleize
%td.w-arbitary
%span{ class: "c-perk-status-tag #{advert.status}" }= advert.status.titleize
%td.w-arbitary= advert.track_slugs
%td.w-arbitary= advert.num_impressions
%td.w-arbitary= advert.num_clicks
%td.w-arbitary= link_to "Details", admin_partner_advert_path(@partner, advert)
Expand Down
15 changes: 10 additions & 5 deletions app/views/admin/perks/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
- require_stylesheet "about"
- require_stylesheet "admin"
.c-admin-page
.lg-container
%h1.text-h1.mb-16 Perk #{@partner.name}##{@perk.id}
%div{ class: 'max-w-[443px]' }= render ViewComponents::Partner::Perk.new(@perk)
%hr.my-32.border-borderColor5

.text-h6.mb-8 Status: #{@perk.status.titleize}
.text-h6.mb-8
Status:
%span{ class: "c-perk-status-tag #{@perk.status}" }= @perk.status.titleize
.text-h6.mb-8 Num Clicks: #{@perk.num_clicks}
.text-h6.mb-8 Preview Text: #{@perk.preview_text}
.text-h6 Preview Text:
%p{ class: 'max-w-[400px] mb-16' }= @perk.preview_text

%h2.text-h2.mb-16 General offer
%h2.text-h2.mb-12 General offer
.text-h6.mb-8 URL: #{@perk.general_url}
.text-h6.mb-8 Offer Summary: #{@perk.general_offer_summary_markdown}
.text-h6.mb-8 Button Text: #{@perk.general_button_text}
.text-h6.mb-8 Offer Details: #{@perk.general_offer_details}
.text-h6.mb-16 Offer Details: #{@perk.general_offer_details}

%h2.text-h2.mb-16 Insiders offer
%h2.text-h2.mb-12 Insiders offer
.text-h6.mb-8 URL: #{@perk.insiders_url}
.text-h6.mb-8 Offer Summary: #{@perk.insiders_offer_summary_markdown}
.text-h6.mb-8 Button Text: #{@perk.insiders_button_text}
Expand Down

0 comments on commit 3a2cdaa

Please sign in to comment.