[BUG #2228] Implemented wallet filtering screen
This commit is contained in:
parent
0403a7cdc1
commit
0730420017
|
@ -3,13 +3,13 @@
|
|||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[reagent.core :as r]
|
||||
[status-im.ui.components.react :refer [view
|
||||
animated-view
|
||||
image
|
||||
text
|
||||
icon
|
||||
touchable-highlight
|
||||
list-view
|
||||
list-item]]
|
||||
animated-view
|
||||
image
|
||||
text
|
||||
icon
|
||||
touchable-highlight
|
||||
list-view
|
||||
list-item]]
|
||||
[status-im.ui.components.chat-icon.screen :refer [chat-icon-view-menu-item]]
|
||||
[status-im.chat.styles.screen :as st]
|
||||
[status-im.i18n :refer [label label-pluralize message-status-label]]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im.constants
|
||||
(:require [status-im.utils.types :as types]
|
||||
(:require [status-im.i18n :as i18n]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.config :as config]))
|
||||
|
||||
(def ethereum-rpc-url "http://localhost:8545")
|
||||
|
@ -25,6 +26,15 @@
|
|||
|
||||
(def default-network "testnet_rpc")
|
||||
|
||||
(def default-wallet-transactions
|
||||
{:filters
|
||||
{:type [{:id :inbound :label (i18n/label :t/incoming) :checked? true}
|
||||
{:id :outbound :label (i18n/label :t/outgoing) :checked? true}
|
||||
{:id :pending :label (i18n/label :t/pending) :checked? true}
|
||||
;; TODO(jeluard) Restore once we support postponing transaction
|
||||
#_
|
||||
{:id :postponed :label (i18n/label :t/postponed) :checked? true}]}})
|
||||
|
||||
(defn- transform-config [networks]
|
||||
(->> networks
|
||||
(map (fn [[network-name {:keys [config] :as data}]]
|
||||
|
|
|
@ -276,6 +276,10 @@
|
|||
:confirmations-helper-text "Please wait for at least 12 confirmations to make sure your transaction is processed securely"
|
||||
:copy-transaction-hash "Copy transaction hash"
|
||||
:open-on-etherscan "Open on Etherscan.io"
|
||||
:incoming "Incoming"
|
||||
:outgoing "Outgoing"
|
||||
:pending "Pending"
|
||||
:postponed "Postponed"
|
||||
|
||||
;;webview
|
||||
:web-view-error "oops, error"
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
(:require-macros [status-im.utils.styles :refer [defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as st]))
|
||||
|
||||
(def wrapper
|
||||
{:padding 16})
|
||||
|
||||
(defnstyle icon-check-container [checked?]
|
||||
{:background-color (if checked? st/color-light-blue st/color-gray5)
|
||||
:alignItems :center
|
||||
:justifyContent :center
|
||||
:margin-right 16
|
||||
:android {:border-radius 2
|
||||
:width 17
|
||||
:height 17}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
(ns status-im.ui.components.checkbox.view
|
||||
(:require [cljs.spec.alpha :as s]
|
||||
[status-im.ui.components.checkbox.styles :as cst]
|
||||
[status-im.ui.components.react :as rn]
|
||||
[status-im.utils.platform :as p]))
|
||||
(:require [reagent.core :as reagent]
|
||||
[status-im.ui.components.checkbox.styles :as styles]
|
||||
[status-im.ui.components.react :as react]))
|
||||
|
||||
(defn checkbox [{:keys [on-press checked?]}]
|
||||
[rn/touchable-highlight {:on-press on-press}
|
||||
[rn/view (cst/icon-check-container checked?)
|
||||
;; TODO(jeluard) Migrate to native checkbox provided by RN 0.49
|
||||
;; https://facebook.github.io/react-native/docs/checkbox.html
|
||||
|
||||
(defn checkbox [{:keys [on-value-change checked?]}]
|
||||
[react/touchable-highlight {:style styles/wrapper :on-press #(do (when on-value-change (on-value-change (not checked?))))}
|
||||
[react/view (styles/icon-check-container checked?)
|
||||
(when checked?
|
||||
[rn/icon :check_on cst/check-icon])]])
|
||||
[react/icon :check_on styles/check-icon])]])
|
|
@ -1,6 +0,0 @@
|
|||
(ns status-im.ui.components.item-checkbox
|
||||
(:require [reagent.core :as r]
|
||||
[status-im.react-native.js-dependencies :as rn-dependencies]))
|
||||
|
||||
(def item-checkbox rn-dependencies/camera)
|
||||
|
|
@ -10,6 +10,12 @@
|
|||
{:flex 1
|
||||
:flex-direction :column})
|
||||
|
||||
(def item-checkbox
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def primary-text-base
|
||||
{:font-size 17
|
||||
:color styles/color-black})
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"
|
||||
(:require [reagent.core :as r]
|
||||
[status-im.ui.components.list.styles :as lst]
|
||||
[status-im.ui.components.checkbox.view :as checkbox]
|
||||
[status-im.ui.components.react :as rn]
|
||||
[status-im.ui.components.icons.vector-icons :as vi]
|
||||
[status-im.utils.platform :as p]))
|
||||
|
@ -72,6 +73,11 @@
|
|||
[& children]
|
||||
(into [rn/view {:style lst/item-text-view}] (keep identity children)))
|
||||
|
||||
(defn item-checkbox
|
||||
[{:keys [style] :as props}]
|
||||
[rn/view {:style (merge style lst/item-checkbox)}
|
||||
[checkbox/checkbox props]])
|
||||
|
||||
(defn- wrap-render-fn [f]
|
||||
(fn [data]
|
||||
;; For details on passed data
|
||||
|
@ -114,9 +120,10 @@
|
|||
(let [{:keys [section]} (js->clj data :keywordize-keys true)]
|
||||
(r/as-element (f section)))))
|
||||
|
||||
(defn- default-render-section-header [{:keys [title]}]
|
||||
[rn/text {:style lst/section-header}
|
||||
title])
|
||||
(defn- default-render-section-header [{:keys [title data]}]
|
||||
(when (seq data)
|
||||
[rn/text {:style lst/section-header}
|
||||
title]))
|
||||
|
||||
(defn- wrap-per-section-render-fn [props]
|
||||
;; TODO(jeluard) Somehow wrapping `:render-fn` does not work
|
||||
|
|
|
@ -75,9 +75,11 @@
|
|||
nil
|
||||
tst/item])
|
||||
|
||||
(defn- icon-action [icon icon-opts handler]
|
||||
(defn- icon-action [icon {:keys [overlay-style] :as icon-opts} handler]
|
||||
[rn/touchable-highlight {:on-press handler}
|
||||
[rn/view {:style (merge tst/item tst/toolbar-action)}
|
||||
(when overlay-style
|
||||
[rn/view overlay-style])
|
||||
[vi/icon icon icon-opts]]])
|
||||
|
||||
(defn actions [v]
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
:tags []
|
||||
:sync-state :done
|
||||
:wallet {}
|
||||
:wallet.transactions constants/default-wallet-transactions
|
||||
:prices {}
|
||||
:notifications {}
|
||||
:network constants/default-network
|
||||
|
@ -177,6 +178,7 @@
|
|||
:discoveries/request-discoveries-timer
|
||||
:discoveries/new-discover
|
||||
:wallet/wallet
|
||||
:wallet/wallet.transactions
|
||||
:prices/prices
|
||||
:prices/prices-loading?
|
||||
:notifications/notifications]))
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
status-im.ui.screens.qr-scanner.events
|
||||
status-im.ui.screens.wallet.events
|
||||
status-im.ui.screens.wallet.send.events
|
||||
status-im.ui.screens.wallet.transactions.events
|
||||
status-im.ui.screens.wallet.choose-recipient.events
|
||||
[re-frame.core :refer [dispatch reg-fx reg-cofx] :as re-frame]
|
||||
[status-im.native-module.core :as status]
|
||||
|
|
|
@ -111,12 +111,3 @@
|
|||
|
||||
(defn asset-border [color]
|
||||
{:border-color color :border-width 1 :border-radius 32})
|
||||
|
||||
(def corner-dot
|
||||
{:position :absolute
|
||||
:top 12
|
||||
:right 6
|
||||
:width 4
|
||||
:height 4
|
||||
:border-radius 2
|
||||
:background-color styles/color-cyan})
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
(ns status-im.ui.screens.wallet.transactions.events
|
||||
(:require [status-im.utils.handlers :as handlers]))
|
||||
|
||||
(defn- mark-all-checked [filters]
|
||||
(update filters :type #(map (fn [m] (assoc m :checked? true)) %)))
|
||||
|
||||
(defn- mark-checked [filters {:keys [type] :as m} checked?]
|
||||
(update filters :type #(map (fn [{:keys [id] :as m}] (if (= type id) (assoc m :checked? checked?) m)) %)))
|
||||
|
||||
(defn- update-filters [db f]
|
||||
(update-in db [:wallet.transactions :filters] f))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:wallet.transactions/filter
|
||||
(fn [db [_ path checked?]]
|
||||
(update-filters db #(mark-checked % path checked?))))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:wallet.transactions/filter-all
|
||||
(fn [db]
|
||||
(update-filters db mark-all-checked)))
|
|
@ -225,3 +225,12 @@
|
|||
{:background-color styles/color-light-gray3
|
||||
:height 1
|
||||
:margin-vertical 10})
|
||||
|
||||
(def corner-dot
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:right 0
|
||||
:width 4
|
||||
:height 4
|
||||
:border-radius 2
|
||||
:background-color styles/color-cyan})
|
|
@ -161,3 +161,7 @@
|
|||
(if (>= confirmations max-confirmations)
|
||||
100
|
||||
(* 100 (/ confirmations max-confirmations))))))
|
||||
|
||||
(reg-sub :wallet.transactions/filters
|
||||
(fn [db]
|
||||
(get-in db [:wallet.transactions :filters])))
|
|
@ -12,18 +12,9 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.screens.wallet.transactions.styles :as transactions.styles]
|
||||
[status-im.ui.screens.wallet.views :as wallet.views]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.utils :as utils])
|
||||
[status-im.utils.money :as money])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn- show-not-implemented! []
|
||||
(utils/show-popup "TODO" "Not implemented yet!"))
|
||||
|
||||
(defn on-sign-transaction
|
||||
[password]
|
||||
;; TODO(yenda) implement
|
||||
(re-frame/dispatch [:accept-transactions password]))
|
||||
|
||||
(defn on-delete-transaction
|
||||
[{:keys [id]}]
|
||||
(re-frame/dispatch [:wallet/discard-unsigned-transaction-with-confirmation id]))
|
||||
|
@ -34,16 +25,22 @@
|
|||
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-sign-all])}
|
||||
(i18n/label :t/transactions-sign-all)])
|
||||
|
||||
(def history-action
|
||||
{:icon :icons/filter
|
||||
:handler #(utils/show-popup "TODO" "Not implemented") #_(re-frame/dispatch [:navigate-to-modal :wallet-transactions-sign-all])})
|
||||
(defn history-action [filter?]
|
||||
(merge
|
||||
{:icon :icons/filter
|
||||
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-filter])}
|
||||
(when filter? {:icon-opts {:overlay-style transactions.styles/corner-dot}})))
|
||||
|
||||
(defn toolbar-view [current-tab unsigned-transactions-count]
|
||||
(defn- all-checked? [filter-data]
|
||||
(and (every? :checked? (:type filter-data))
|
||||
(every? :checked? (:tokens filter-data))))
|
||||
|
||||
(defn- toolbar-view [current-tab unsigned-transactions-count filter-data]
|
||||
[toolbar/toolbar {:flat? true}
|
||||
toolbar/default-nav-back
|
||||
[toolbar/content-title (i18n/label :t/transactions)]
|
||||
(case current-tab
|
||||
:transactions-history [toolbar/actions [history-action]]
|
||||
:transactions-history [toolbar/actions [(history-action (not (all-checked? filter-data)))]]
|
||||
:unsigned-transactions nil)]) ;; TODO (andrey) implement [unsigned-action unsigned-transactions-count]
|
||||
|
||||
|
||||
|
@ -106,14 +103,22 @@
|
|||
;; TODO(yenda) hook with re-frame
|
||||
(defn- empty-text [s] [react/text {:style transactions.styles/empty-text} s])
|
||||
|
||||
(defn filtered-transaction? [transaction filter-data]
|
||||
;; TODO(jeluard) extend to token when available
|
||||
(:checked? (some #(when (= (:type transaction) (:id %)) %) (:type filter-data))))
|
||||
|
||||
(defn update-transactions [m filter-data]
|
||||
(update m :data (fn [v] (filter #(filtered-transaction? % filter-data) v))))
|
||||
|
||||
(defview history-list []
|
||||
(letsubs [transactions-history-list [:wallet.transactions/transactions-history-list]
|
||||
transactions-loading? [:wallet.transactions/transactions-loading?]
|
||||
error-message [:wallet.transactions/error-message?]]
|
||||
[react/view {:style styles/flex}
|
||||
error-message [:wallet.transactions/error-message?]
|
||||
filter-data [:wallet.transactions/filters]]
|
||||
[react/view styles/flex
|
||||
(when error-message
|
||||
[wallet.views/error-message-view transactions.styles/error-container transactions.styles/error-message])
|
||||
[list/section-list {:sections transactions-history-list
|
||||
[list/section-list {:sections (map #(update-transactions % filter-data) transactions-history-list)
|
||||
:render-fn render-transaction
|
||||
:empty-component (empty-text (i18n/label :t/transactions-history-empty))
|
||||
:on-refresh #(re-frame/dispatch [:update-transactions])
|
||||
|
@ -128,47 +133,43 @@
|
|||
|
||||
;; Filter history
|
||||
|
||||
(defn- item-tokens [{:keys [symbol label checked?]}]
|
||||
(defn- item-filter [{:keys [icon checked? path]} content]
|
||||
[list/item
|
||||
[list/item-icon (transaction-type->icon :pending)] ;; TODO(jeluard) add proper token data
|
||||
[list/item-icon icon]
|
||||
content
|
||||
[list/item-checkbox {:checked? checked? :on-value-change #(re-frame/dispatch [:wallet.transactions/filter path %])}]])
|
||||
|
||||
#_ ;; TODO(jeluard) Will be used for ERC20 tokens
|
||||
(defn- item-filter-tokens [{:keys [symbol label checked?]}]
|
||||
[item-filter {:icon (transaction-type->icon :pending) :checked? checked?} ;; TODO(jeluard) add proper token icon
|
||||
[list/item-content
|
||||
[list/item-primary label]
|
||||
[list/item-secondary symbol]]
|
||||
[checkbox/checkbox {:checked? true #_checked?}]])
|
||||
[list/item-secondary symbol]]])
|
||||
|
||||
(defn- item-type [{:keys [id label checked?]}]
|
||||
[list/item
|
||||
[list/item-icon (transaction-type->icon (keyword id))]
|
||||
[list/item-content
|
||||
[list/item-primary-only label]]
|
||||
[checkbox/checkbox checked?]])
|
||||
(defn- item-filter-type [{:keys [id label checked?]}]
|
||||
(let [kid (keyword id)]
|
||||
[item-filter {:icon (transaction-type->icon kid) :checked? checked? :path {:type kid}}
|
||||
[list/item-content
|
||||
[list/item-primary-only label]]]))
|
||||
|
||||
(def filter-data
|
||||
[{:title (i18n/label :t/transactions-filter-tokens)
|
||||
:key :tokens
|
||||
:renderItem (list/wrap-render-fn item-tokens)
|
||||
:data [{:symbol "GNO" :label "Gnosis"}
|
||||
{:symbol "SNT" :label "Status Network Token"}
|
||||
{:symbol "SGT" :label "Status Genesis Token"}
|
||||
{:symbol "GOL" :label "Golem"}]}
|
||||
{:title (i18n/label :t/transactions-filter-type)
|
||||
:key :type
|
||||
:renderItem (list/wrap-render-fn item-type)
|
||||
:data [{:id :incoming :label "Incoming"}
|
||||
{:id :outgoing :label "Outgoing"}
|
||||
{:id :pending :label "Pending"}
|
||||
{:id :postponed :label "Postponed"}]}])
|
||||
(defn- wrap-filter-data [m]
|
||||
;; TODO(jeluard) Restore tokens filtering once token support is added
|
||||
[{:title (i18n/label :t/transactions-filter-type)
|
||||
:key :type
|
||||
:renderItem (list/wrap-render-fn item-filter-type)
|
||||
:data (:type m)}])
|
||||
|
||||
(defview filter-history []
|
||||
[]
|
||||
[react/view
|
||||
[toolbar/toolbar {}
|
||||
[toolbar/nav-clear-text (i18n/label :t/done)]
|
||||
[toolbar/content-title (i18n/label :t/transactions-filter-title)]
|
||||
[toolbar/text-action {:handler #(utils/show-popup "TODO" "Select All")}
|
||||
(i18n/label :t/transactions-filter-select-all)]]
|
||||
[react/view {:style styles/flex}
|
||||
[list/section-list {:sections filter-data}]]])
|
||||
(letsubs [filter-data [:wallet.transactions/filters]]
|
||||
[react/view styles/flex
|
||||
[toolbar/toolbar {}
|
||||
[toolbar/nav-clear-text (i18n/label :t/done)]
|
||||
[toolbar/content-title (i18n/label :t/transactions-filter-title)]
|
||||
[toolbar/text-action {:handler #(re-frame/dispatch [:wallet.transactions/filter-all])
|
||||
:disabled? (all-checked? filter-data)}
|
||||
(i18n/label :t/transactions-filter-select-all)]]
|
||||
[react/view {:style styles/flex}
|
||||
[list/section-list {:sections (wrap-filter-data filter-data)}]]]))
|
||||
|
||||
(defn history-tab [active?]
|
||||
[react/text {:uppercase? true
|
||||
|
@ -195,10 +196,11 @@
|
|||
|
||||
(defview transactions []
|
||||
(letsubs [unsigned-transactions-count [:wallet.transactions/unsigned-transactions-count]
|
||||
current-tab [:get :view-id]]
|
||||
current-tab [:get :view-id]
|
||||
filter-data [:wallet.transactions/filters]]
|
||||
[react/view {:style styles/flex}
|
||||
[status-bar/status-bar]
|
||||
[toolbar-view current-tab unsigned-transactions-count]
|
||||
[toolbar-view current-tab unsigned-transactions-count filter-data]
|
||||
[tabs/swipable-tabs tabs-list current-tab true
|
||||
{:navigation-event :navigation-replace
|
||||
:tab-style transactions.styles/tab
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
(def autolink #js {:default #js {}})
|
||||
(def config #js {:default #js {}})
|
||||
(def camera #js {:constants #js {}})
|
||||
(def circle-checkbox #js {})
|
||||
(def contacts #js {})
|
||||
(def dialogs #js {})
|
||||
(def dismiss-keyboard #js {})
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
[status-im.test.accounts.events]
|
||||
[status-im.test.wallet.events]
|
||||
[status-im.test.wallet.transactions.subs]
|
||||
[status-im.test.wallet.transactions.views]
|
||||
[status-im.test.profile.events]
|
||||
[status-im.test.bots.events]
|
||||
[status-im.test.chat.models.input]
|
||||
|
@ -37,6 +38,7 @@
|
|||
'status-im.test.wallet.events
|
||||
'status-im.test.bots.events
|
||||
'status-im.test.wallet.transactions.subs
|
||||
'status-im.test.wallet.transactions.views
|
||||
'status-im.test.chat.models.input
|
||||
'status-im.test.i18n
|
||||
'status-im.test.utils.utils
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
(ns status-im.test.wallet.transactions.views
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[status-im.ui.screens.wallet.transactions.views :as views]))
|
||||
|
||||
(deftest filtered-transaction?
|
||||
(is (not (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :outbound :checked? true}]}))))
|
||||
(is (not (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :inbound :checked? false}]}))))
|
||||
(is (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :inbound :checked? true}]})))
|
||||
(is (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :outbound :checked? true} {:id :inbound :checked? true}]}))))
|
||||
|
||||
(deftest update-transactions
|
||||
(is (= {:data '()} (views/update-transactions {:data {:type :inbound}} {:type [{:id :outbound :checked? true}]}))))
|
Loading…
Reference in New Issue