From 095e6466616b60e620a7408723e6279fdd3d6ad4 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Wed, 1 Jul 2020 21:33:10 -0400 Subject: [PATCH] Added ShopPanel to home sidebar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Added: - ShopPanel to home sidebar - DIssenter shop redux, api route/controller --- app/controllers/api/v1/shop_controller.rb | 33 ++++++ app/javascript/gabsocial/actions/shop.js | 47 ++++++++ .../gabsocial/components/panel/shop_panel.js | 102 ++++++++++++++++++ app/javascript/gabsocial/pages/home_page.js | 2 + app/javascript/gabsocial/reducers/index.js | 2 + app/javascript/gabsocial/reducers/shop.js | 41 +++++++ config/routes.rb | 1 + 7 files changed, 228 insertions(+) create mode 100644 app/controllers/api/v1/shop_controller.rb create mode 100644 app/javascript/gabsocial/actions/shop.js create mode 100644 app/javascript/gabsocial/components/panel/shop_panel.js create mode 100644 app/javascript/gabsocial/reducers/shop.js diff --git a/app/controllers/api/v1/shop_controller.rb b/app/controllers/api/v1/shop_controller.rb new file mode 100644 index 00000000..a285e037 --- /dev/null +++ b/app/controllers/api/v1/shop_controller.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class Api::V1::ShopController < Api::BaseController + before_action :require_user! + + respond_to :json + + skip_before_action :set_cache_headers + + def index + type = params[:type] + if type == 'featured_products' + body = Redis.current.get("gabstore:featuredproducts") + + if body.nil? + uri = URI("https://shop.dissenter.com/product/group/json") + uri.query = URI.encode_www_form({}) + + res = Net::HTTP.get_response(uri) + if res.is_a?(Net::HTTPSuccess) + body = res.body + Redis.current.set("gabstore:featuredproducts", res.body) + Redis.current.expire("gabstore:featuredproducts", 15.minutes.seconds) + end + end + + render json: body + else + raise GabSocial::NotPermittedError + end + end + +end diff --git a/app/javascript/gabsocial/actions/shop.js b/app/javascript/gabsocial/actions/shop.js new file mode 100644 index 00000000..d89387ab --- /dev/null +++ b/app/javascript/gabsocial/actions/shop.js @@ -0,0 +1,47 @@ +import api from '../api' +import { me } from '../initial_state' + +export const SHOP_FEATURED_PRODUCTS_FETCH_REQUEST = 'SHOP_FEATURED_PRODUCTS_FETCH_REQUEST' +export const SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS = 'SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS' +export const SHOP_FEATURED_PRODUCTS_FETCH_FAIL = 'SHOP_FEATURED_PRODUCTS_FETCH_FAIL' + +export const fetchFeaturedProducts = () => { + return function (dispatch, getState) { + if (!me) return + + dispatch(fetchFeaturedProductsRequest('featured')) + + api(getState).get(`/api/v1/shop?type=featured_products`).then((response) => { + try { + dispatch(fetchFeaturedProductsSuccess(response.data.data, 'featured')) + } catch (error) { + // + } + }).catch(function (error) { + dispatch(fetchFeaturedProductsFail(error, 'featured')) + }) + } +} + +function fetchFeaturedProductsRequest(listType) { + return { + type: SHOP_FEATURED_PRODUCTS_FETCH_REQUEST, + listType, + } +} + +function fetchFeaturedProductsSuccess(items, listType) { + return { + type: SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS, + items, + listType, + } +} + +function fetchFeaturedProductsFail(error, listType) { + return { + type: SHOP_FEATURED_PRODUCTS_FETCH_FAIL, + error, + listType, + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/panel/shop_panel.js b/app/javascript/gabsocial/components/panel/shop_panel.js new file mode 100644 index 00000000..6dabdee2 --- /dev/null +++ b/app/javascript/gabsocial/components/panel/shop_panel.js @@ -0,0 +1,102 @@ +import { defineMessages, injectIntl } from 'react-intl' +import { fetchFeaturedProducts } from '../../actions/shop' +import PanelLayout from './panel_layout' +import Image from '../image' +import Text from '../text' + +const messages = defineMessages({ + title: { id: 'shop_panel.title', defaultMessage: 'Dissenter Shop' }, + shop_now: { id: 'shop_panel.shop_now', defaultMessage: 'Visit the Dissenter Shop' }, +}) + +const mapStateToProps = (state) => ({ + items: state.getIn(['shop', 'featured', 'items']), + isError: state.getIn(['shop', 'featured', 'isError']), +}) + +const mapDispatchToProps = (dispatch) => ({ + onFetchFeaturedProducts: () => dispatch(fetchFeaturedProducts()), +}) + +export default +@connect(mapStateToProps, mapDispatchToProps) +@injectIntl +class ShopPanel extends PureComponent { + + static propTypes = { + intl: PropTypes.object.isRequired, + products: PropTypes.array, + isLazy: PropTypes.bool, + onFetchFeaturedProducts: PropTypes.func.isRequired, + isError: PropTypes.bool.isRequired, + } + + state = { + fetched: !this.props.isLazy, + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (nextProps.shouldLoad && !prevState.fetched) { + return { fetched: true } + } + + return null + } + + componentDidUpdate(prevProps, prevState) { + if (!prevState.fetched && this.state.fetched) { + this.props.onFetchFeaturedProducts() + } + } + + componentDidMount() { + if (!this.props.isLazy) { + this.props.onFetchFeaturedProducts() + } + } + + render() { + const { + intl, + items, + isError, + } = this.props + + if (!items || isError || !Array.isArray(items)) return null + + return ( + +
+ { + items.map((block) => ( + + + + + {block.name} + + + )) + } +
+
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/pages/home_page.js b/app/javascript/gabsocial/pages/home_page.js index 64ba06f8..fdf56655 100644 --- a/app/javascript/gabsocial/pages/home_page.js +++ b/app/javascript/gabsocial/pages/home_page.js @@ -9,6 +9,7 @@ import GroupsPanel from '../components/panel/groups_panel' import ListsPanel from '../components/panel/lists_panel' import LinkFooter from '../components/link_footer' import WhoToFollowPanel from '../components/panel/who_to_follow_panel' +import ShopPanel from '../components/panel/shop_panel' import ProgressPanel from '../components/panel/progress_panel' import ProPanel from '../components/panel/pro_panel' import UserPanel from '../components/panel/user_panel' @@ -103,6 +104,7 @@ class HomePage extends PureComponent { + diff --git a/app/javascript/gabsocial/reducers/index.js b/app/javascript/gabsocial/reducers/index.js index 607954a2..11763720 100644 --- a/app/javascript/gabsocial/reducers/index.js +++ b/app/javascript/gabsocial/reducers/index.js @@ -29,6 +29,7 @@ import relationships from './relationships' import reports from './reports' import search from './search' import settings from './settings' +import shop from './shop' import sidebar from './sidebar' import statuses from './statuses' import status_lists from './status_lists' @@ -69,6 +70,7 @@ const reducers = { reports, search, settings, + shop, sidebar, statuses, status_lists, diff --git a/app/javascript/gabsocial/reducers/shop.js b/app/javascript/gabsocial/reducers/shop.js new file mode 100644 index 00000000..ac383564 --- /dev/null +++ b/app/javascript/gabsocial/reducers/shop.js @@ -0,0 +1,41 @@ +import { + SHOP_FEATURED_PRODUCTS_FETCH_REQUEST, + SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS, + SHOP_FEATURED_PRODUCTS_FETCH_FAIL, +} from '../actions/shop' +import { + Map as ImmutableMap, + List as ImmutableList, + fromJS, +} from 'immutable' + +const initialState = ImmutableMap({ + featured: ImmutableMap({ + items: ImmutableList(), + isError: false, + isLoading: false, + }), +}) + +export default function suggestionsReducer(state = initialState, action) { + switch(action.type) { + case SHOP_FEATURED_PRODUCTS_FETCH_REQUEST: + return state.withMutations((map) => { + map.setIn([action.listType, 'isError'], false) + map.setIn([action.listType, 'isLoading'], true) + }) + case SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS: + return state.withMutations((map) => { + map.setIn([action.listType, 'items'], action.items) + map.setIn([action.listType, 'isError'], false) + map.setIn([action.listType, 'isLoading'], false) + }) + case SHOP_FEATURED_PRODUCTS_FETCH_FAIL: + return state.withMutations((map) => { + map.setIn([action.listType, 'isError'], true) + map.setIn([action.listType, 'isLoading'], false) + }) + default: + return state + } +} diff --git a/config/routes.rb b/config/routes.rb index 9b57f7fc..5c6c2a94 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -327,6 +327,7 @@ Rails.application.routes.draw do end resources :gab_trends, only: [:index] + resources :shop, only: [:index] resources :streaming, only: [:index] resources :custom_emojis, only: [:index] resources :suggestions, only: [:index, :destroy]