diff --git a/src/features/rewards/adRowsDetails/__snapshots__/spec.tsx.snap b/src/features/rewards/adRowsDetails/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..acb450e79 --- /dev/null +++ b/src/features/rewards/adRowsDetails/__snapshots__/spec.tsx.snap @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Ad Rows Details tests basic tests matches the snapshot 1`] = ` +.c4 { + font-family: Muli,sans-serif; + font-size: 14px; + color: #686978; + display: inline-block; +} + +.c1 { + cursor: pointer; + white-space: nowrap; +} + +.c0 { + text-align: left; + padding-top: 15px; +} + +.c5 { + width: 94.5%; + padding-left: 10px; + display: inline-block; +} + +.c6 { + color: #DADCE8; + background-color: #DADCE8; + height: 2px; + border: none; +} + +.c2 { + margin: 0; + background: none; + border: none; + width: 16px; + height: 16px; + color: #9E9FAB; + padding: 1px; + outline: none; + display: inline-block; + text-align: center; +} + +.c3 { + width: 100%; + height: 100%; + fill: currentColor; +} + + + +
+
+
+ +
+
+ +
+
+
+
+
+
+ + +`; diff --git a/src/features/rewards/adRowsDetails/index.tsx b/src/features/rewards/adRowsDetails/index.tsx new file mode 100644 index 000000000..033fa1199 --- /dev/null +++ b/src/features/rewards/adRowsDetails/index.tsx @@ -0,0 +1,100 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { + StyledAdPortionTD, + StyledAdsDateRow, + StyledAdsDetailRow, + StyledCaratIcon, + StyledDateText, + StyledHR, + StyledHRDiv, + StyledInnerStartTD, + StyledSpaceDiv + } from './style' +import { + CaratTriangleDownSIcon, CaratTriangleRightSIcon +} from '../../../components/icons' +import { DetailRow } from '../tableAdsHistory' +import { Row, Cell } from '../../../components/dataTables/table' + +export interface Props { + id?: string + row?: DetailRow + rowIndex?: number + detailRows?: Row[] +} + +interface State { + innerDetailVisible: boolean +} + +export default class AdRowsDetails extends React.PureComponent { + constructor (props: Props) { + super(props) + this.state = { + innerDetailVisible: true + } + } + + setInnerVisible = () => { + this.setState({ + innerDetailVisible: !this.state.innerDetailVisible + }) + } + + render () { + const { row, rowIndex, detailRows } = this.props + return ( + <> + + + + + + { + this.state.innerDetailVisible + ? + : + } + + + { + row ? row.date : '' + } + + + + + + + + + { + detailRows && this.state.innerDetailVisible ? + detailRows.map((detailRow: Row, j: number) => { + return ( + + { + detailRow.content.map((detailCell: Cell, k: number) => { + return k === 0 ? + + + + : + + {detailCell.content} + + }) + } + + ) + }) + : null + } + + ) + } +} diff --git a/src/features/rewards/adRowsDetails/spec.tsx b/src/features/rewards/adRowsDetails/spec.tsx new file mode 100644 index 000000000..60d17cb7d --- /dev/null +++ b/src/features/rewards/adRowsDetails/spec.tsx @@ -0,0 +1,24 @@ +/* global jest, expect, describe, it, afterEach */ +import * as React from 'react' +import { shallow } from 'enzyme' +import { create } from 'react-test-renderer' +import { TestThemeProvider } from '../../../theme' +import AdRowsDetails from './index'; + +describe('Ad Rows Details tests', () => { + const baseComponent = (props?: object) => + + describe('basic tests', () => { + it('matches the snapshot', () => { + const component = baseComponent() + const tree = create(component).toJSON() + expect(tree).toMatchSnapshot() + }) + + it('renders the component', () => { + const wrapper = shallow(baseComponent()) + const assertion = wrapper.find('#adRowsDetails').length + expect(assertion).toBe(1) + }) + }) +}) diff --git a/src/features/rewards/adRowsDetails/style.ts b/src/features/rewards/adRowsDetails/style.ts new file mode 100644 index 000000000..4893a14fa --- /dev/null +++ b/src/features/rewards/adRowsDetails/style.ts @@ -0,0 +1,72 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License. v. 2.0. If a copy of the MPL was not distributed with this file. + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'styled-components' + +export const StyledDateText = styled<{}, 'div'>('div')` + font-family: Muli, sans-serif; + font-size: 14px; + color: #686978; + display: inline-block; +` +export const StyledAdsDateRow = styled<{}, 'div'>('div')` + cursor: pointer; + white-space: nowrap; +` + +export const StyledAdsDetailRow = styled<{}, 'div'>('div')` + text-align: left; + padding-top: 15px; +` + +export const StyledHRDiv = styled<{}, 'div'>('div')` + width: 94.5%; + padding-left: 10px; + display: inline-block; +` + +export const StyledHR = styled<{}, 'hr'>('hr')` + color: #DADCE8; + background-color: #DADCE8; + height: 2px; + border: none; +` + +export const StyledCaratIcon = styled<{}, 'div'>('div')` + margin: 0; + background: none; + border: none; + width: 16px; + height: 16px; + color: #9E9FAB; + padding: 1px; + outline: none; + display: inline-block; + text-align: center; +` + +export const StyledAdPortionTD = styled<{}, 'td'>('td')` + font-family: Muli, sans-serif; + font-size: 14px; + font-weight: 500; + color: #686978; + border-bottom: none; + padding: 5px 0; + text-align: left; +` + +export const StyledInnerStartTD = styled<{}, 'td'>('td')` + font-family: Muli, sans-serif; + font-size: 14px; + font-weight: 500; + color: #686978; + border-bottom: none; + padding: 12px 0; + text-align: left; + height: 0%; +` + +export const StyledSpaceDiv = styled<{}, 'div'>('div')` + min-width: 55px; +` diff --git a/src/features/rewards/categoryLikePicker/__snapshots__/spec.tsx.snap b/src/features/rewards/categoryLikePicker/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..da012e4e7 --- /dev/null +++ b/src/features/rewards/categoryLikePicker/__snapshots__/spec.tsx.snap @@ -0,0 +1,147 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Category Like Picker tests basic tests matches the snapshot 1`] = ` +Array [ + .c0 { + display: inline-block; +} + +.c1 { + margin: auto; + border: none; + height: 32px; + width: 32px; + outline: none; + cursor: pointer; + object-fit: cover; +} + +.c2 { + width: 100%; + height: 100%; + fill: currentColor; +} + +
+
+ +
+
, + .c0 { + display: inline-block; +} + +.c6 { + border: none; + height: 31px; + width: 31px; + outline: none; + cursor: pointer; +} + +.c7 { + width: 100%; + height: 100%; + fill: currentColor; +} + +.c1 { + display: inline-block; + position: relative; +} + +.c2 { + left: 50%; + top: calc(100% + 10px); + -webkit-transform: translateX(-80%); + -ms-transform: translateX(-80%); + transform: translateX(-80%); + white-space: nowrap; + position: absolute; + background: #0C0D21; + text-align: center; + padding: 10px; + z-index: 2; + border-radius: 3px; + box-shadow: 1px 1px 5px 0 rgba(34,35,38,0.43); + display: none; +} + +.c4 { + color: #FFFFFF; + font-family: Muli,sans-serif; + font-weight: 300; + font-size: 14px; +} + +.c3 { + width: 0; + height: 0; + border-style: solid; + position: absolute; + top: -7px; + left: calc(80% - 10px); + border-width: 0 7px 8px 7px; + border-color: transparent transparent #0C0D21 transparent; +} + +.c5 { + cursor: pointer; + height: 24px; +} + +
+
+
+
+
+ MISSING: optOutTooltip +
+
+
+
+ +
+
+
+
, +] +`; diff --git a/src/features/rewards/categoryLikePicker/index.tsx b/src/features/rewards/categoryLikePicker/index.tsx new file mode 100644 index 000000000..0b30486bb --- /dev/null +++ b/src/features/rewards/categoryLikePicker/index.tsx @@ -0,0 +1,125 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { + StyledCategoryActionOptinLogo, + StyledCategoryActionOptoutLogo, + StyledCategoryActionOptinButton, + StyledCategoryActionOptoutButton, + StyledCategoryActionOptinFilledButton, + StyledCategoryActionOptoutFilledButton +} from './style' +import { + HeartLIcon, + HeartSIcon, + BlockLIcon, + BlockSIcon +} from '../../../components/icons' +import { Tooltip } from '..' +import { getLocale } from '../../../helpers' + +interface State { + itemSelected: number +} + +export interface Props { + id?: string + optAction: number + onOptIn?: () => void + onOptOut?: () => void +} + +export default class ThumbLikePicker extends React.PureComponent { + constructor (props: Props) { + super(props) + this.state = { + itemSelected: props.optAction + } + } + + componentWillReceiveProps (nextProps: Props) { + if ('optAction' in nextProps) { + this.setState({ itemSelected: nextProps.optAction }) + } + } + + showCategoryLike = () => { + return ( + <> + + + + + + + + + + + + + + ) + } + + showCategoryBlock = () => { + return ( + <> + + + + + + + + + + + + + + ) + } + + showCategoryUnselected = () => { + return ( + <> + + + + + + + + + + + + + + ) + } + + render () { + return ( + this.state.itemSelected === 1 ? + this.showCategoryLike() + : + this.state.itemSelected === 2 ? + this.showCategoryBlock() + : + this.showCategoryUnselected() + ) + } +} diff --git a/src/features/rewards/categoryLikePicker/spec.tsx b/src/features/rewards/categoryLikePicker/spec.tsx new file mode 100644 index 000000000..c0636950b --- /dev/null +++ b/src/features/rewards/categoryLikePicker/spec.tsx @@ -0,0 +1,24 @@ +/* global jest, expect, describe, it, afterEach */ +import * as React from 'react' +import { shallow } from 'enzyme' +import { create } from 'react-test-renderer' +import { TestThemeProvider } from '../../../theme' +import CategoryLikePicker from './index'; + +describe('Category Like Picker tests', () => { + const baseComponent = (props?: object) => + + describe('basic tests', () => { + it('matches the snapshot', () => { + const component = baseComponent() + const tree = create(component).toJSON() + expect(tree).toMatchSnapshot() + }) + + it('renders the component', () => { + const wrapper = shallow(baseComponent()) + const assertion = wrapper.find('#categoryLikePicker').length + expect(assertion).toBe(1) + }) + }) +}) diff --git a/src/features/rewards/categoryLikePicker/style.ts b/src/features/rewards/categoryLikePicker/style.ts new file mode 100644 index 000000000..b5658ca25 --- /dev/null +++ b/src/features/rewards/categoryLikePicker/style.ts @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License. v. 2.0. If a copy of the MPL was not distributed with this file. +* You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'styled-components' + +export const StyledCategoryActionOptinLogo = styled<{}, 'div'>('div')` + display: inline-block; +` + +export const StyledCategoryActionOptoutLogo = styled<{}, 'div'>('div')` + display: inline-block; +` + +export const StyledCategoryActionOptinButton = styled<{}, 'div'>('div')` +margin: auto; + border: none; + height: 32px; + width: 32px; + outline: none; + cursor: pointer; + object-fit: cover; +` + +export const StyledCategoryActionOptoutButton = styled<{}, 'div'>('div')` + border: none; + height: 31px; + width: 31px; + outline: none; + cursor: pointer; +` + +export const StyledCategoryActionOptinFilledButton = styled(StyledCategoryActionOptinButton)` + color: red; +` + +export const StyledCategoryActionOptoutFilledButton = styled(StyledCategoryActionOptoutButton)` + color: red; +` diff --git a/src/features/rewards/dropMenu/__snapshots__/spec.tsx.snap b/src/features/rewards/dropMenu/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..9fb55a4cb --- /dev/null +++ b/src/features/rewards/dropMenu/__snapshots__/spec.tsx.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Drop Menu tests basic tests matches the snapshot 1`] = ` +.c0 { + width: 32px; + height: 32px; + display: inline-block; + padding: 2px; + position: relative; + border: none; + outline: none; +} + +.c1 { + width: 100%; + height: 100%; + fill: currentColor; +} + +
+
+ +
+
+`; diff --git a/src/features/rewards/dropMenu/index.tsx b/src/features/rewards/dropMenu/index.tsx new file mode 100644 index 000000000..fab8574eb --- /dev/null +++ b/src/features/rewards/dropMenu/index.tsx @@ -0,0 +1,108 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { + StyledAdMenuDropContent, + StyledAdStatBulletMenuIcon, + StyledAdMenuOptionDropContent, + StyledAdMenuOptionDropContentText +} from './style' +import { MoreVertLIcon } from '../../../components/icons' +import { getLocale } from '../../../helpers' + +interface State { + menuOpen: boolean +} + +export interface Props { + id?: string + currentlySaved: boolean + currentlyFlagged: boolean + onMenuSave?: () => void + onMenuFlag?: () => void +} + +export default class DropMenu extends React.PureComponent { + private container: React.RefObject + constructor (props: Props) { + super(props) + this.state = { + menuOpen: false + } + this.container = React.createRef() + } + + componentDidMount () { + document.addEventListener('mousedown', this.handleClickOutside) + } + + componentWillUnmount () { + document.removeEventListener('mousedown', this.handleClickOutside) + } + + handleClickOutside = (event: MouseEvent) => { + if (this.container.current && !this.container.current.contains(event.target as Element)) { + this.setState({ + menuOpen: false + }) + } + } + + showMenu = () => { + this.setState({ + menuOpen: !this.state.menuOpen + }) + } + + render () { + const { onMenuFlag, onMenuSave, currentlySaved, currentlyFlagged } = this.props + return ( + +
+ + { + this.state.menuOpen ? + + + { + !currentlySaved ? + + { + getLocale('saveAd') + } + + : + + { + getLocale('removeAdFromSaved') + } + + } + + + { + !currentlyFlagged ? + + { + getLocale('markAsInappropriate') + } + + : + + { + getLocale('markAsInappropriateChecked') + } + + } + + + : + null + } +
+
+ ) + } +} diff --git a/src/features/rewards/dropMenu/spec.tsx b/src/features/rewards/dropMenu/spec.tsx new file mode 100644 index 000000000..bebf9a6c8 --- /dev/null +++ b/src/features/rewards/dropMenu/spec.tsx @@ -0,0 +1,24 @@ +/* global jest, expect, describe, it, afterEach */ +import * as React from 'react' +import { shallow } from 'enzyme' +import { create } from 'react-test-renderer' +import { TestThemeProvider } from '../../../theme' +import DropMenu from './index'; + +describe('Drop Menu tests', () => { + const baseComponent = (props?: object) => + + describe('basic tests', () => { + it('matches the snapshot', () => { + const component = baseComponent() + const tree = create(component).toJSON() + expect(tree).toMatchSnapshot() + }) + + it('renders the component', () => { + const wrapper = shallow(baseComponent()) + const assertion = wrapper.find('#dropMenu').length + expect(assertion).toBe(1) + }) + }) +}) diff --git a/src/features/rewards/dropMenu/style.ts b/src/features/rewards/dropMenu/style.ts new file mode 100644 index 000000000..067f2654d --- /dev/null +++ b/src/features/rewards/dropMenu/style.ts @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License. v. 2.0. If a copy of the MPL was not distributed with this file. +* You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'styled-components' + +export const StyledAdMenuDropContent = styled<{}, 'div'>('div')` + display: block; + position: absolute; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; + margin-top: -10px; + background-color: white; + border: 1px solid; + border-color: #DADCE8; + border-radius: 5px; + min-width: 200px; +` + +export const StyledAdStatBulletMenuIcon = styled<{}, 'div'>('div')` + width: 32px; + height: 32px; + display: inline-block; + padding: 2px; + position: relative; + border: none; + outline: none; +` + +export const StyledAdMenuOptionDropContent = styled<{}, 'div'>('div')` + display: flex; + align-items: center; + height: 35px; + padding-left: 5px; + margin-top: auto; + cursor: pointer; + &:hover { + background-color: #B0DBFF; + } +` + +export const StyledAdMenuOptionDropContentText = styled<{}, 'span'>('span')` + font-size: 16px; + vertical-align: middle; + font-weight: 600; +` diff --git a/src/features/rewards/index.ts b/src/features/rewards/index.ts index 165575b79..20a81d493 100644 --- a/src/features/rewards/index.ts +++ b/src/features/rewards/index.ts @@ -2,10 +2,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +import AdRowsDetails from './adRowsDetails' import Alert from './alert' import Amount from './amount' import Box from './box' import BoxAlert from './boxAlert' +import CategoryLikePicker from './categoryLikePicker' import DisabledBox from './disabledBox' import DisabledContent from './disabledContent' import DisabledPanel from './disabledPanel' @@ -27,18 +29,22 @@ import ModalBackupRestore from './modalBackupRestore' import ModalContribute from './modalContribute' import ModalDonation from './modalDonation' import ModalPending from './modalPending' +import ModalShowAdsHistory from './modalShowAdsHistory' import NextContribution from './nextContribution' import PanelWelcome from './panelWelcome' import Profile from './profile' import RestoreSites from './restoreSites' import RewardsButton from './rewardsButton' import SettingsPage from './settingsPage' +import ShowAdsHistory from './showAdsHistory' import SiteBanner from './siteBanner' import Tab from './tab' +import TableAdsHistory from './tableAdsHistory' import TableContribute from './tableContribute' import TableDonation from './tableDonation' import TablePending from './tablePending' import TableTransactions from './tableTransactions' +import ThumbLikePicker from './thumbLikePicker' import Tip from './tip' import ToggleTips from './toggleTips' import Tokens from './tokens' @@ -53,10 +59,12 @@ import WalletWrapper from './walletWrapper' import WelcomePage from './welcomePage' export { + AdRowsDetails, Alert, Amount, Box, BoxAlert, + CategoryLikePicker, DisabledBox, DisabledContent, DisabledPanel, @@ -78,18 +86,22 @@ export { ModalContribute, ModalDonation, ModalPending, + ModalShowAdsHistory, NextContribution, PanelWelcome, Profile, RestoreSites, RewardsButton, SettingsPage, + ShowAdsHistory, SiteBanner, Tab, + TableAdsHistory, TableContribute, TableDonation, TablePending, TableTransactions, + ThumbLikePicker, Tip, ToggleTips, Tokens, diff --git a/src/features/rewards/modalShowAdsHistory/__snapshots__/spec.tsx.snap b/src/features/rewards/modalShowAdsHistory/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..e205bdfea --- /dev/null +++ b/src/features/rewards/modalShowAdsHistory/__snapshots__/spec.tsx.snap @@ -0,0 +1,180 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ModalShowAdsHistory tests basic tests matches the snapshot 1`] = ` +.c5 { + font-family: Poppins,sans-serif; + padding-top: 10px; + white-space: nowrap; +} + +.c6 { + font-size: 22px; + font-weight: 600; + color: rgb(193,45,124); + margin-bottom: 10px; + line-height: 1.3; +} + +.c7 { + font-size: 30px; + line-height: 1.2; + margin-bottom: 10px; + font-weight: 300; +} + +.c10 { + font-size: 18px; + color: rgb(193,45,124); +} + +.c9 { + line-height: 1.5; +} + +.c11 { + font-size: 18px; + color: rgb(193,45,124); + font-weight: 600; +} + +.c8 { + line-height: 1.5; + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-align-items: baseline; + -webkit-box-align: baseline; + -ms-flex-align: baseline; + align-items: baseline; +} + +.c0 { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background: rgba(12,13,33,0.85); + z-index: 99; + padding: 0 20px; + overflow: hidden; +} + +.c1 { + max-width: 920px; + margin: 52px auto; + background: #fff; + border-radius: 6px; + overflow: hidden; + position: relative; +} + +.c2 { + position: absolute; + top: 20px; + right: 20px; + cursor: pointer; + width: 20px; + height: 20px; + color: #9E9FAB; +} + +.c4 { + padding: 48px 48px; + overflow-y: auto; + max-height: calc(100vh - 100px); +} + +.c3 { + width: 100%; + height: 100%; + fill: currentColor; +} + +.c12 { + -webkit-text-decoration: none; + text-decoration: none; + font-size: 16px; + font-weight: 400; + padding-top: 24px; +} + + +`; diff --git a/src/features/rewards/modalShowAdsHistory/index.tsx b/src/features/rewards/modalShowAdsHistory/index.tsx new file mode 100644 index 000000000..df2c79ba0 --- /dev/null +++ b/src/features/rewards/modalShowAdsHistory/index.tsx @@ -0,0 +1,170 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { + StyledAdsHeaderWrapper, + StyledAdsHistoryTitle, + StyledAdsInfoText, + StyledAdsInfoTextWrapper, + StyledAdsPerHourText, + StyledAdsSaveFiltered, + StyledNotSelectedLink, + StyledLink, + StyledSeparatorText, + StyledSubTitleText, + StyledText, + StyledThumbDownFilter, + StyledThumbDownNotSelectedFilter, + StyledWrapper +} from './style' +import Modal from '../../../components/popupModals/modal/index' +import { getLocale } from '../../../helpers' +import TableAdsHistory, { DetailRow } from '../tableAdsHistory/index' +import { ThumbsupSIcon } from '../../../components/icons' + +export interface Props { + rows?: DetailRow[] + onClose?: () => void + id?: string + isMobile?: boolean + adsPerHour?: number + adsPerDay?: number + hasSavedEntries?: boolean + onSavedFilterClick?: () => void + onAllFilterClick?: () => void + onThumbFilterClick?: () => void +} + +interface State { + filterStatus: number +} + +export default class ModalShowAdsHistory extends React.PureComponent { + constructor (props: Props) { + super(props) + this.state = { + filterStatus: 0 + } + } + + get headers () { + return [ + getLocale('date'), + getLocale('ads'), + getLocale('category') + ] + } + + onSavedFilterClick = () => { + this.setState({ + filterStatus: 1 + }) + const savedFilterFn = this.props.onSavedFilterClick + if (savedFilterFn) { + savedFilterFn() + } + } + + onAllFilterClick = () => { + this.setState({ + filterStatus: 0 + }) + const allFilterFn = this.props.onAllFilterClick + if (allFilterFn) { + allFilterFn() + } + } + + onThumbFilterClick = () => { + this.setState({ + filterStatus: 2 + }) + const thumbFilterFn = this.props.onThumbFilterClick + if (thumbFilterFn) { + thumbFilterFn() + } + } + + render () { + const { id, onClose, isMobile, adsPerHour, hasSavedEntries, rows } = this.props + + return ( + + + + {getLocale('adsHistoryTitle')} + + + {getLocale('adsHistorySubTitle')} + + + + + {getLocale('adsCurrentlyViewing')} + + + {(adsPerHour || '0') + (adsPerHour !== 1 ? getLocale('adsPerHourPlural') : getLocale('adsPerHourSingular'))} + + + { + rows && hasSavedEntries ? + + + { + this.state.filterStatus !== 0 ? + + { + getLocale('all') + } + : + + { + getLocale('all') + } + + } + + | + + { + this.state.filterStatus !== 1 ? + + { + getLocale('saved') + } + : + + { + getLocale('saved') + } + + } + + | + + { + this.state.filterStatus !== 2 ? + + + : + + + + } + + + : null + } + + + + + ) + } +} diff --git a/src/features/rewards/modalShowAdsHistory/spec.tsx b/src/features/rewards/modalShowAdsHistory/spec.tsx new file mode 100644 index 000000000..c44bcac56 --- /dev/null +++ b/src/features/rewards/modalShowAdsHistory/spec.tsx @@ -0,0 +1,24 @@ +/* global jest, expect, describe, it, afterEach */ +import * as React from 'react' +import { shallow } from 'enzyme' +import { create } from 'react-test-renderer' +import ModalShowAdsHistory from './index' +import { TestThemeProvider } from '../../../theme' + +describe('ModalShowAdsHistory tests', () => { + const baseComponent = (props?: object) => + + describe('basic tests', () => { + it('matches the snapshot', () => { + const component = baseComponent() + const tree = create(component).toJSON() + expect(tree).toMatchSnapshot() + }) + + it('renders the component', () => { + const wrapper = shallow(baseComponent()) + const assertion = wrapper.find('#modal').length + expect(assertion).toBe(1) + }) + }) +}) diff --git a/src/features/rewards/modalShowAdsHistory/style.ts b/src/features/rewards/modalShowAdsHistory/style.ts new file mode 100644 index 000000000..cef8496a8 --- /dev/null +++ b/src/features/rewards/modalShowAdsHistory/style.ts @@ -0,0 +1,118 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this file, +* You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +import styled from 'styled-components' + +export const StyledWrapper = styled<{}, 'div'>('div')` + font-family: Poppins, sans-serif; + padding-top: 10px; + white-space: nowrap; +` + +export const StyledLink = styled<{}, 'a'>('a')` + cursor: pointer; + display: inline-block; + color: #CED0DB; + font-size: 16px; + letter-spacing: 0; +` + +export const StyledNotSelectedLink = styled<{}, 'span'>('span')` + display: inline-block; + color: #696FDC; + font-size: 16px; + letter-spacing: 0; +` + +export const StyledText = styled<{}, 'span'>('span')` + font-size: 16px; + letter-spacing: 0; + display: inline-block; + color: #C2C4CF; + margin: 0 10px 0; +` + +export const StyledAdsHistoryTitle = styled<{}, 'div'>('div')` + font-size: 22px; + font-weight: 600; + color: rgb(193, 45, 124); + margin-bottom: 10px; + line-height: 1.3; +` + +export const StyledNote = styled<{}, 'div'>('div')` + max-width: 508px; + font-family: Muli,sans-serif; + font-size: 12px; + font-weight: 300; + margin-bottom: 10px; + line-height: 1.5; + color: #686978; +` + +export const StyledSeparatorText = styled<{}, 'span'>('span')` + font-size: 16px; + font-weight: 200; + letter-spacing: 0; + display: inline-block; + color: #C2C4CF +` + +export const StyledSubTitleText = styled<{}, 'div'>('div')` + font-size: 30px; + line-height: 1.2; + margin-bottom: 10px; + font-weight: 300; +` + +export const StyledAdsInfoText = styled<{}, 'span'>('span')` + font-size: 18px; + color: rgb(193, 45, 124); +` + +export const StyledAdsInfoTextWrapper = styled<{}, 'div'>('div')` + line-height: 1.5; +` + +export const StyledAdsPerHourText = styled<{}, 'span'>('span')` + font-size: 18px; + color: rgb(193, 45, 124); + font-weight: 600; +` + +export const StyledAdsHeaderWrapper = styled<{}, 'div'>('div')` + line-height: 1.5; + width: 100%; + display: flex; + justify-content: space-between; + align-items: baseline; +` + +export const StyledAdsSaveFiltered = styled<{}, 'div'>('div')` + text-align: right; + line-height: 1.5; + display: flex; + justify-content: space-between; +` + +export const StyledThumbDownFilter = styled<{}, 'div'>('div')` + display: inline-block; + width: 32px; + height: 32px; + margin-top: auto; + padding: 4px; + padding-top: 0px; + cursor: pointer; + color: CED0DB; +` + +export const StyledThumbDownNotSelectedFilter = styled<{}, 'div'>('div')` + display: inline-block; + width: 32px; + height: 32px; + color: #696FDC; + padding: 4px; + padding-top: 0px; +` diff --git a/src/features/rewards/showAdsHistory/__snapshots__/spec.tsx.snap b/src/features/rewards/showAdsHistory/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..04cce803d --- /dev/null +++ b/src/features/rewards/showAdsHistory/__snapshots__/spec.tsx.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ShowAdsHistory tests basic tests matches the snapshot 1`] = ` +.c0 { + padding-top: 10px; + text-align: right; +} + +.c1 { + display: inline-block; + color: #CED0DB; + cursor: pointer; + font-size: 13px; + font-weight: normal; + -webkit-letter-spacing: 0; + -moz-letter-spacing: 0; + -ms-letter-spacing: 0; + letter-spacing: 0; +} + +
+ + MISSING: openAdsHistory + +
+`; diff --git a/src/features/rewards/showAdsHistory/index.tsx b/src/features/rewards/showAdsHistory/index.tsx new file mode 100644 index 000000000..a1b8284d7 --- /dev/null +++ b/src/features/rewards/showAdsHistory/index.tsx @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { + StyledLink, + StyledWrapper, + StyledDisabledLink +} from './style' + +import { getLocale } from '../../../helpers' + +export interface Props { + onAdsHistoryOpen?: () => void + notEmpty: boolean +} + +export default class ShowAdsHistory extends React.PureComponent { + render () { + const { onAdsHistoryOpen, notEmpty } = this.props + + return ( + + { + notEmpty ? + + {getLocale('openAdsHistory')} + : + + {getLocale('openAdsHistory')} + + } + + ) + } +} diff --git a/src/features/rewards/showAdsHistory/spec.tsx b/src/features/rewards/showAdsHistory/spec.tsx new file mode 100644 index 000000000..b3a5bd31d --- /dev/null +++ b/src/features/rewards/showAdsHistory/spec.tsx @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this file, +* You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +import * as React from 'react' +import { shallow } from 'enzyme' +import { create } from 'react-test-renderer' +import ShowAdsHistory from './index'; +import { TestThemeProvider } from '../../../theme' + +describe('ShowAdsHistory tests', () => { + const baseComponent = (props?: object) => + + describe('basic tests', () => { + it('matches the snapshot', () => { + const component = baseComponent() + const tree = create(component).toJSON() + expect(tree).toMatchSnapshot() + }) + + it('renders the component', () => { + const wrapper = shallow(baseComponent()) + const assertion = wrapper.find('#disabled-panel').length + expect(assertion).toBe(1) + }) + }) +}) diff --git a/src/features/rewards/showAdsHistory/style.ts b/src/features/rewards/showAdsHistory/style.ts new file mode 100644 index 000000000..137fda79d --- /dev/null +++ b/src/features/rewards/showAdsHistory/style.ts @@ -0,0 +1,29 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this file, +* You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +import styled from 'styled-components' + +export const StyledWrapper = styled<{}, 'div'>('div')` + padding-top: 10px; + text-align: right; +` + +export const StyledLink = styled<{}, 'a'>('a')` + cursor: pointer; + display: inline-block; + color: #696FDC; + font-size: 13px; + font-weight: normal; + letter-spacing: 0; +` + +export const StyledDisabledLink = styled<{}, 'span'>('span')` + display: inline-block; + color: #CED0DB; + cursor: pointer; + font-size: 13px; + font-weight: normal; + letter-spacing: 0; +` diff --git a/src/features/rewards/tableAdsHistory/__snapshots__/spec.tsx.snap b/src/features/rewards/tableAdsHistory/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..3f9e6c341 --- /dev/null +++ b/src/features/rewards/tableAdsHistory/__snapshots__/spec.tsx.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Amount tests basic tests matches the snapshot 1`] = ` +.c0 { + -webkit-text-decoration: none; + text-decoration: none; + font-size: 16px; + font-weight: 400; + padding-top: 24px; +} + +
+
+ MISSING: noAdsHistory +
+
+`; diff --git a/src/features/rewards/tableAdsHistory/index.tsx b/src/features/rewards/tableAdsHistory/index.tsx new file mode 100644 index 000000000..d60a8be5e --- /dev/null +++ b/src/features/rewards/tableAdsHistory/index.tsx @@ -0,0 +1,244 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { + StyledDateTH, + StyledAdTH, + StyledCategoryTH, + StyledAdContentDiv, + StyledLogo, + StyledLogoDiv, + StyledAdInfoDiv, + StyledAdBrand, + StyledAdInfo, + StyledAdStatDiv, + StyledAdStat, + StyledAdStatActions, + StyledCategoryContentDiv, + StyledCategoryName, + StyledCategoryActions, + StyledAdLink, + StyledNoAdHistoryDiv, + StyledNoLogoDiv, + StyledTD +} from './style' +import { Row } from '../../../components/dataTables/table' +import { StyledTable } from '../../../components/dataTables/table/style' +import ThumbLikePicker from '../thumbLikePicker' +import CategoryLikePicker from '../categoryLikePicker' +import DropMenu from '../dropMenu' +import AdRowsDetails from '../adRowsDetails' +import { getLocale } from '../../../helpers' + +export interface DetailRow { + id: string + date: string + adDetailRows: AdDetailRow[] +} + +interface AdContent { + brand: string + brandInfo: string + brandLogo: string + brandUrl: string + brandDisplayUrl: string + likeAction: number + adAction: 'click' | 'dismiss' | 'view' | 'landed' + savedAd: boolean + flaggedAd: boolean + logoUrl?: string + onThumbUpPress?: () => void + onThumbDownPress?: () => void + onMenuSave?: () => void + onMenuFlag?: () => void +} + +interface CategoryContent { + category: string + optAction: number + onOptInAction?: () => void + onOptOutAction?: () => void +} + +export interface AdDetailRow { + id: string + adContent: AdContent + categoryContent: CategoryContent +} + +export interface Props { + header: string[] + id?: string + testId?: string + children?: React.ReactNode + headerColor?: boolean + rows?: DetailRow[] + allItems: number +} + +export default class TableAdsHistory extends React.PureComponent { + getAdsHistoryTable = (header: string[], rows: DetailRow[]): any => { + return ( + + { + header ? + + + { + this.getHeader(header) + } + + + : null + } + + { + this.getRows(rows) + } + + + ) + } + + getHeader = (header: string[]) => { + if (!header) { + return + } + + return ( + <> + {header[0]} + {header[1]} + {header[2]} + + ) + } + + getRows = (rows: DetailRow[]) => { + return rows.map((row: DetailRow, i: number) => { + const detailRows = this.getDetailRows(row.adDetailRows) + return ( + detailRows && detailRows.length > 0 ? + + : null + ) + }) + } + + getCategoryContent = (content: CategoryContent) => { + return ( + + + {content.category} + + + + + + ) + } + + getAdContent = (content: AdContent) => { + return ( + + + { + content.logoUrl ? + + + + : + + } + + {content.brand} + {content.brandInfo} + {content.brandDisplayUrl} + + + + + {getLocale(content.adAction)} + +
+ + + + + + + ) + } + + getDetailRows = (rows: AdDetailRow[]): Row[] | undefined => { + if (!rows) { + return + } + let filteredRows = rows + if (this.props.allItems === 1) { + filteredRows = rows.filter((row: AdDetailRow) => { + return row.adContent && row.adContent.savedAd + }) + } else if (this.props.allItems === 2) { + filteredRows = rows.filter((row: AdDetailRow) => { + return row.adContent && row.adContent.likeAction === 1 + }) + } + return filteredRows.map((row: AdDetailRow, i: number): Row => { + const cell: Row = { + content: [ + { + content: ( + + ) + }, + { + content: ( + this.getAdContent(row.adContent) + ) + }, + { + content: ( + this.getCategoryContent(row.categoryContent) + ) + } + ] + } + return cell + }) + } + + render () { + const { id, testId, header, rows } = this.props + return ( +
+ { + rows ? + this.getAdsHistoryTable(header, rows) + : + + { + getLocale('noAdsHistory') + } + + } +
+ + ) + } +} diff --git a/src/features/rewards/tableAdsHistory/spec.tsx b/src/features/rewards/tableAdsHistory/spec.tsx new file mode 100644 index 000000000..91aa46566 --- /dev/null +++ b/src/features/rewards/tableAdsHistory/spec.tsx @@ -0,0 +1,24 @@ +/* global jest, expect, describe, it, afterEach */ +import * as React from 'react' +import { shallow } from 'enzyme' +import { create } from 'react-test-renderer' +import { TestThemeProvider } from '../../../theme' +import TableAdsHistory from './index'; + +describe('Amount tests', () => { + const baseComponent = (props?: object) => + + describe('basic tests', () => { + it('matches the snapshot', () => { + const component = baseComponent() + const tree = create(component).toJSON() + expect(tree).toMatchSnapshot() + }) + + it('renders the component', () => { + const wrapper = shallow(baseComponent()) + const assertion = wrapper.find('#tableAdsHistory').length + expect(assertion).toBe(1) + }) + }) +}) diff --git a/src/features/rewards/tableAdsHistory/style.ts b/src/features/rewards/tableAdsHistory/style.ts new file mode 100644 index 000000000..45aca09b1 --- /dev/null +++ b/src/features/rewards/tableAdsHistory/style.ts @@ -0,0 +1,171 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License. v. 2.0. If a copy of the MPL was not distributed with this file. +* You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'styled-components' + +export const StyledDateTH = styled<{}, 'th'>('th')` + text-transform: uppercase; + text-align: left; + font-family: ${p => p.theme.fontFamily.body}; + font-size: 12px; + font-weight: 500; + border-bottom: 2px solid #dedfe4; + border-top: 2px solid #dedfe4; + color: #4B4C5C; + padding: 12px 0; + min-width: 55px; +` + +export const StyledAdTH = styled<{}, 'th'>('th')` + text-transform: uppercase; + text-align: left; + font-family: ${p => p.theme.fontFamily.body}; + font-size: 12px; + font-weight: 500; + border-bottom: 2px solid #dedfe4; + border-top: 2px solid #dedfe4; + color: #4B4C5C; + padding: 12px 0; + min-width: 550px; +` + +export const StyledCategoryTH = styled<{}, 'th'>('th')` + text-transform: uppercase; + text-align: left; + font-family: ${p => p.theme.fontFamily.body}; + font-size: 12px; + font-weight: 500; + border-bottom: 2px solid #dedfe4; + border-top: 2px solid #dedfe4; + color: #4B4C5C; + padding: 12px 0; + min-width: 220px; +` + +export const StyledOuterTD = styled<{}, 'td'>('td')` + width: 100%; +` + +export const StyledTR = styled<{}, 'tr'>('tr')` + text-align: left; +` + +export const StyledToggleWrap = styled<{}, 'div'>('div')` + text-align: right; +` + +export const StyledToggle = styled<{}, 'div'>('div')` + font-family: Poppins, sans-serif; + font-size: 13px; + color: #4c54d2; + text-transform: capitalize; + background: none; + border: none; + padding: 0; + cursor: pointer; +` + +export const StyledAdLink = styled<{}, 'a'>('a')` + text-decoration: none; + cursor: pointer; + display: flex; + color: #686978 +` + +export const StyledAdTable = styled<{}, 'table'>('table')` + min-width: 100%; + margin: 24px 0; + padding-top: 15px; +` +export const StyledAdContentDiv = styled<{}, 'div'>('div')` + min-width: 550px; + border: 1px solid; + border-collapse: separate; + border-radius: 5px; + border-color: #DADCE8; + padding: 10px; + display: inline-flex; + align-items: center; + height: 85px; +` + +export const StyledLogo = styled<{}, 'img'>('img') ` + width: 64px; + height: 64px; +` + +export const StyledLogoDiv = styled<{}, 'div'>('div')` + display: inline-block; + width: 64px; + height: 64px; + padding: 1px; + padding-right: 10px; +` + +export const StyledNoLogoDiv = styled<{}, 'div'>('div')` + display: none; +` + +export const StyledAdInfoDiv = styled<{}, 'div'>('div')` + padding-left: 20px; + display: inline-block; +` +export const StyledAdInfo = styled<{}, 'div'>('div')` + display: block; + color: #AEB1C2; + padding-bottom: 2px; +` + +export const StyledAdBrand = styled<{}, 'div'>('div')` + font-family: Poppins, sans-serif; + font-weight: 600; + padding-bottom: 2px; +` + +export const StyledAdStatDiv = styled<{}, 'div'>('div')` + margin-left: auto; + height: 100%; + display: flex; + flex-direction: column; + padding-top: 5px; + padding-bottom: 5px; +` + +export const StyledAdStat = styled<{}, 'div'>('div')` + padding-left: 2px; +` + +export const StyledAdStatActions = styled<{}, 'div'>('div')` + margin-top: auto; +` + +export const StyledCategoryContentDiv = styled<{}, 'div'>('div')` + display: flex; + flex-direction: column; + height: 85px; + min-width: 220px; + padding: 15px; +` + +export const StyledCategoryName = styled<{}, 'div'>('div')` + font-size: 16px; + font-weight: 600; + margin: auto; +` + +export const StyledCategoryActions = styled<{}, 'div'>('div')` + margin: auto; +` + +export const StyledNoAdHistoryDiv = styled<{}, 'div'>('div')` + text-decoration: none; + font-size: 16px; + font-weight: 400; + padding-top: 24px; +` + +export const StyledTD = styled<{}, 'td'>('td')` + width: 15%; + border: 'none'; +` diff --git a/src/features/rewards/thumbLikePicker/__snapshots__/spec.tsx.snap b/src/features/rewards/thumbLikePicker/__snapshots__/spec.tsx.snap new file mode 100644 index 000000000..22d81b8c2 --- /dev/null +++ b/src/features/rewards/thumbLikePicker/__snapshots__/spec.tsx.snap @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Amount tests basic tests matches the snapshot 1`] = ` +Array [ + .c0 { + display: inline-block; + width: 32px; + height: 32px; + padding: 4px; + cursor: pointer; +} + +.c1 { + width: 100%; + height: 100%; + fill: currentColor; +} + +
+ +
, + .c0 { + display: inline-block; + width: 32px; + height: 32px; + margin-top: auto; + padding: 4px; + cursor: pointer; +} + +.c1 { + width: 100%; + height: 100%; + fill: currentColor; +} + +
+ +
, +] +`; diff --git a/src/features/rewards/thumbLikePicker/index.tsx b/src/features/rewards/thumbLikePicker/index.tsx new file mode 100644 index 000000000..b9f8a91eb --- /dev/null +++ b/src/features/rewards/thumbLikePicker/index.tsx @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { + StyledAdStatThumbUpIcon, + StyledAdStatThumbUpFilledIcon, + StyledAdStatThumbDownIcon, + StyledAdStatThumbDownFilledIcon +} from './style' + +import { + ThumbsupLIcon, + ThumbsdownLIcon, + ThumbsupSIcon, + ThumbsdownSIcon +} from '../../../components/icons' + +interface State { + itemSelected: number +} + +export interface Props { + id?: string + likeAction: number + onThumbUpPress?: () => void + onThumbDownPress?: () => void +} + +export default class ThumbLikePicker extends React.PureComponent { + constructor (props: Props) { + super(props) + this.state = { + itemSelected: props.likeAction + } + } + + componentWillReceiveProps (nextProps: Props) { + if ('likeAction' in nextProps) { + this.setState({ itemSelected: nextProps.likeAction }) + } + } + + render () { + return ( + <> + { + this.state.itemSelected === 1 ? + <> + + + + + + + + : + this.state.itemSelected === 2 ? + <> + + + + + + + + : + <> + + + + + + + + } + + ) + } +} diff --git a/src/features/rewards/thumbLikePicker/spec.tsx b/src/features/rewards/thumbLikePicker/spec.tsx new file mode 100644 index 000000000..bda21a57b --- /dev/null +++ b/src/features/rewards/thumbLikePicker/spec.tsx @@ -0,0 +1,24 @@ +/* global jest, expect, describe, it, afterEach */ +import * as React from 'react' +import { shallow } from 'enzyme' +import { create } from 'react-test-renderer' +import { TestThemeProvider } from '../../../theme' +import ThumbLikePicker from './index'; + +describe('Amount tests', () => { + const baseComponent = (props?: object) => + + describe('basic tests', () => { + it('matches the snapshot', () => { + const component = baseComponent() + const tree = create(component).toJSON() + expect(tree).toMatchSnapshot() + }) + + it('renders the component', () => { + const wrapper = shallow(baseComponent()) + const assertion = wrapper.find('#thumbLikePicker').length + expect(assertion).toBe(1) + }) + }) +}) diff --git a/src/features/rewards/thumbLikePicker/style.ts b/src/features/rewards/thumbLikePicker/style.ts new file mode 100644 index 000000000..c7130e08f --- /dev/null +++ b/src/features/rewards/thumbLikePicker/style.ts @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License. v. 2.0. If a copy of the MPL was not distributed with this file. +* You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'styled-components' + +export const StyledAdStatThumbUpIcon = styled<{}, 'div'>('div')` + display: inline-block; + width: 32px; + height: 32px; + padding: 4px; + cursor: pointer; +` + +export const StyledAdStatThumbUpFilledIcon = styled(StyledAdStatThumbUpIcon)` + color: red; +` + +export const StyledAdStatThumbDownIcon = styled<{}, 'div'>('div')` + display: inline-block; + width: 32px; + height: 32px; + margin-top: auto; + padding: 4px; + cursor: pointer; +` + +export const StyledAdStatThumbDownFilledIcon = styled(StyledAdStatThumbDownIcon)` + color: red; +` diff --git a/src/features/rewards/tooltip/index.tsx b/src/features/rewards/tooltip/index.tsx index 67e73f3ee..f63342405 100644 --- a/src/features/rewards/tooltip/index.tsx +++ b/src/features/rewards/tooltip/index.tsx @@ -16,6 +16,7 @@ export interface Props { id?: string content: React.ReactNode children?: React.ReactNode + rightEdge?: boolean } interface State { @@ -40,12 +41,15 @@ export default class Tooltip extends React.PureComponent { } render () { - const { id, content, children } = this.props + const { id, content, children, rightEdge } = this.props return ( - - + + {content} diff --git a/src/features/rewards/tooltip/style.ts b/src/features/rewards/tooltip/style.ts index 88e87feec..9a770df45 100644 --- a/src/features/rewards/tooltip/style.ts +++ b/src/features/rewards/tooltip/style.ts @@ -7,6 +7,7 @@ import styled from 'styled-components' interface StyleProps { displayed?: boolean + rightEdge?: boolean } export const StyledWrapper = styled<{}, 'div'>('div')` @@ -17,7 +18,7 @@ export const StyledWrapper = styled<{}, 'div'>('div')` export const StyledTooltip = styled('div')` left: 50%; top: calc(100% + 10px); - transform: translateX(-50%); + transform: ${p => p.rightEdge ? 'translateX(-80%);' : 'translateX(-50%);'}; white-space: nowrap; position: absolute; background: #0C0D21; @@ -35,13 +36,13 @@ export const StyledTooltipText = styled<{}, 'div'>('div')` font-size: 14px; ` -export const StyledPointer = styled<{}, 'div'>('div')` +export const StyledPointer = styled('div')` width: 0; height: 0; border-style: solid; position: absolute; top: -7px; - left: calc(50% - 7px); + left: ${p => p.rightEdge ? 'calc(80% - 10px)' : 'calc(50% - 7px)'}; border-width: 0 7px 8px 7px; border-color: transparent transparent #0C0D21 transparent; ` diff --git a/stories/assets/img/tesla.jpg b/stories/assets/img/tesla.jpg new file mode 100644 index 000000000..c5da80917 Binary files /dev/null and b/stories/assets/img/tesla.jpg differ diff --git a/stories/assets/locale.ts b/stories/assets/locale.ts index a62aafd28..e19a492b5 100644 --- a/stories/assets/locale.ts +++ b/stories/assets/locale.ts @@ -13,8 +13,20 @@ const locale: Record = { addFundsQR: 'Show QR Code', addFundsText: 'Be sure to use the address below that matches the type of cryto you own. It will be converted automatically to BAT by Uphold and appear as an increased balance in your Brave Rewards wallet. Please allow up to one hour for your wallet balance to update.', addFundsTitle: 'Send cryptocurrency from your external account to your Brave Rewards wallet.', + ads: 'Ads', + adsCurrentlyViewing: 'Your setting: maximum ', adsEarnings: 'earned from ads', + adsHistoryFilterAll: 'All', + adsHistoryFilterSaved: 'Saved', + adsHistorySubTitle: 'Ads you\'ve received in the past 7 days', + adsHistoryTitle: 'Ads History', adsNotSupported: 'Sorry! Ads are not yet available in your region.', + adsPerDayPlural: ' ads per day', + adsPerDaySingular: ' ad per day', + adsPerHourContinuation: ', total ', + adsPerHourPlural: ' ads per hour', + adsPerHourSingular: ' ad per hour', + all: 'All', allowTip: 'Allow tips on', amount: 'Amount', and: 'and', @@ -41,7 +53,9 @@ const locale: Record = { captchaProveHuman: 'Prove that you are human!', captchaTarget: 'target.', captchaMissedTarget: 'Hmm… Not Quite. Try Again.', + category: 'Category', claim: 'Claim', + click: 'Clicked', closeBalance: 'Closing Balance', contribute: 'Contribute', contributeAllocation: 'Auto-Contribute Allocation', @@ -60,6 +74,7 @@ const locale: Record = { disabledPanelText: 'You are not currently accruing any Rewards benefits while browsing. Turn Rewards back on in', disabledPanelTextTwo: 'Earn by viewing privacy-respecting ads, and pay it forward to support content creators you love.', disabledPanelTitle: 'Brave Rewards is', + dismiss: 'Closed', dndCaptchaText1: 'Drag and drop the token logo onto the', dndCaptchaText2: 'target', donation: 'Donation', @@ -90,9 +105,12 @@ const locale: Record = { grantExpire: 'Grant Expiration Date', import: 'import', includeInAuto: 'Include in Auto-Contribute', + landed: 'Clicked', learnMore: 'Learn More', makeMonthly: 'Make this monthly', manageWallet: 'Manage Your Wallet', + markAsInappropriate: 'Mark As Inappropriate', + markAsInappropriateChecked: 'Mark As Inappropriate ✓', monthApr: 'Apr', monthAug: 'August', monthDec: 'December', @@ -109,6 +127,7 @@ const locale: Record = { monthlyTips: 'Monthly Tips!', newGrant: 'A free token grant is available.', noActivity: 'No activities yet…', + noAdsHistory: 'There is currently no Brave Ads history', noGrants: 'Currently no token grant is available.', notEnoughTokens: 'Not enough tokens. Please', noThankYou: 'No, thank you', @@ -117,6 +136,7 @@ const locale: Record = { on: 'on', oneTime: 'One time', oneTimeDonation: 'One-time Tips', + openAdsHistory: 'Show Ads History', openBalance: 'Opening Balance', payment: 'Payment', paymentMonthly: 'Payment made every {{day}}th day in each month.', @@ -147,6 +167,7 @@ const locale: Record = { recurringDonations: 'Monthly Tips', remove: 'remove', reservedAllLink: 'Show all pending contributions', + removeAdFromSaved: 'Remove From Saved', reservedAmountText: 'You’ve designated {{reservedAmount}} BAT for creators who haven’t yet signed up to receive contributions. We’ll keep trying to contribute until they verify, or until 90 days have passed.', reservedMoreLink: 'Learn more.', restore: 'Restore', @@ -186,7 +207,9 @@ const locale: Record = { rewardsRestoreText4: 'Enter your recovery key or', rewardsSummary: 'Rewards Summary', rewardsWhy: 'Why Brave Rewards…', + saveAd: 'Save', saveAsFile: 'Save', + saved: 'Saved', seeAllItems: 'See all {{numItems}} items', seeAllSites: 'See all {{numSites}} sites', sendDonation: 'Send my donation', @@ -206,6 +229,7 @@ const locale: Record = { supportedSites: 'Supported Sites', thankYou: 'Thank You!', termsOfService: 'Terms of Service', + optOutTooltip: 'You will no longer receive\nads from this category', tipOnLike: 'Tip on like', tipText: 'You\'ve just sent a tip to:', titleBAT: 'Basic Attention token (BAT)', @@ -229,6 +253,7 @@ const locale: Record = { unVerifiedTextMore: 'Learn more.', verifiedPublisher: 'Verified Creator', viewDetails: 'View Details', + view: 'Viewed', viewMonthly: 'View Monthly Statement for Details', walletActivity: 'Wallet Activity', walletAddress: 'Wallet Address', diff --git a/stories/features/rewards/modal.tsx b/stories/features/rewards/modal.tsx index 0be5995d8..5731b69cd 100644 --- a/stories/features/rewards/modal.tsx +++ b/stories/features/rewards/modal.tsx @@ -12,12 +12,14 @@ import { DetailRow as ContributeRow } from '../../../src/features/rewards/tableC import { DetailRow as DonationDetailRow } from '../../../src/features/rewards/tableDonation' import { DetailRow as TransactionsRow } from '../../../src/features/rewards/tableTransactions' import { DetailRow as PendingDetailRow } from '../../../src/features/rewards/tablePending' +import { DetailRow as AdsHistoryRow } from '../../../src/features/rewards/tableAdsHistory' import { ModalContribute, ModalBackupRestore, ModalActivity, ModalDonation, - ModalPending + ModalPending, + ModalShowAdsHistory } from '../../../src/features/rewards' import ModalAddFunds, { Address } from '../../../src/features/rewards/modalAddFunds' @@ -27,6 +29,7 @@ const wiki = require('../../assets/img/wiki.jpg') const buzz = require('../../assets/img/buzz.jpg') const guardian = require('../../assets/img/guardian.jpg') const eich = require('../../assets/img/eich.jpg') +const tesla = require('../../assets/img/tesla.jpg') const doNothing = () => { console.log('nothing') @@ -529,3 +532,185 @@ storiesOf('Feature Components/Rewards/Modal', module) /> ) }) + .add('Show Ads History',() => { + const adsPerHour = 2 + const adId: number = 0 + const rowId: number = 0 + const rows: AdsHistoryRow[] = [ + { + id: rowId.toString(), + date: '1/30', + adDetailRows: [ + { + id: adId.toString(), + adContent: { + brand: 'Pepsi', + brandLogo: '', + brandUrl: 'https://www.pepsi.com', + brandDisplayUrl: 'pepsi.com', + brandInfo: 'Animation & VFX Degree - Degree in Animation |', + adAction: 'view', + likeAction: 1, + onThumbUpPress: doNothing, + onThumbDownPress: doNothing, + onMenuFlag: doNothing, + onMenuSave: doNothing, + savedAd: false, + flaggedAd: false + }, + categoryContent: { + category: 'Entertainment', + optAction: 0, + onOptInAction: doNothing, + onOptOutAction: doNothing + } + }, + { + id: (adId + 1).toString(), + adContent: { + brand: 'TESLA', + brandLogo: '', + brandUrl: 'https://www.tesla.com', + brandDisplayUrl: 'tesla.com', + brandInfo: 'Animation & VFX Degree - Degree in Animation |', + adAction: 'click', + likeAction: 2, + onThumbUpPress: doNothing, + onThumbDownPress: doNothing, + onMenuFlag: doNothing, + onMenuSave: doNothing, + savedAd: true, + flaggedAd: false, + logoUrl: tesla + }, + categoryContent: { + category: 'Technology & Computing', + optAction: 0, + onOptInAction: doNothing, + onOptOutAction: doNothing + } + }, + { + id: (adId + 2).toString(), + adContent: { + brand: 'Disney', + brandLogo: '', + brandUrl: 'https://www.disney.com', + brandDisplayUrl: 'disney.com', + brandInfo: 'Animation & VFX Degree - Degree in Animation |', + adAction: 'click', + likeAction: 0, + onThumbUpPress: doNothing, + onThumbDownPress: doNothing, + onMenuFlag: doNothing, + onMenuSave: doNothing, + savedAd: false, + flaggedAd: false + }, + categoryContent: { + category: 'Travel', + optAction: 0, + onOptInAction: doNothing, + onOptOutAction: doNothing + } + } + ] + }, + { + id: (rowId + 1).toString(), + date: '1/29', + adDetailRows: [ + { + id: (adId + 3).toString(), + adContent: { + brand: 'Puma', + brandLogo: '', + brandUrl: 'https://www.puma.com', + brandDisplayUrl: 'puma.com', + brandInfo: 'Animation & VFX Degree - Degree in Animation |', + adAction: 'landed', + likeAction: 1, + onThumbUpPress: doNothing, + onThumbDownPress: doNothing, + onMenuFlag: doNothing, + onMenuSave: doNothing, + savedAd: false, + flaggedAd: false + }, + categoryContent: { + category: 'Sports', + optAction: 1, + onOptInAction: doNothing, + onOptOutAction: doNothing + } + }, + { + id: (adId + 4).toString(), + adContent: { + brand: 'Expedia.com', + brandLogo: '', + brandUrl: 'https://www.expedia.com', + brandDisplayUrl: 'expedia.com', + brandInfo: 'Animation & VFX Degree - Degree in Animation |', + adAction: 'view', + likeAction: 0, + onThumbUpPress: doNothing, + onThumbDownPress: doNothing, + onMenuFlag: doNothing, + onMenuSave: doNothing, + savedAd: true, + flaggedAd: true + }, + categoryContent: { + category: 'Travel', + optAction: 2, + onOptInAction: doNothing, + onOptOutAction: doNothing + } + }, + { + id: (adId + 5).toString(), + adContent: { + brand: 'H&M', + brandLogo: '', + brandUrl: 'https://www.hm.com', + brandDisplayUrl: 'hm.com', + brandInfo: 'Animation & VFX Degree - Degree in Animation |', + adAction: 'dismiss', + likeAction: 0, + onThumbUpPress: doNothing, + onThumbDownPress: doNothing, + onMenuFlag: doNothing, + onMenuSave: doNothing, + savedAd: true, + flaggedAd: false + }, + categoryContent: { + category: 'Fashion', + optAction: 1, + onOptInAction: doNothing, + onOptOutAction: doNothing + } + } + ] + } + ] + return ( + + ) + }) + .add('Show Empty Ads History',() => { + const adsPerHour = 0 + return ( + + ) + })