use modals in matamo & origin

pull/1852/head
filip mertens 3 years ago
parent eb11ba7842
commit 53fd20b28e
  1. 12
      libs/remix-ui/app/src/lib/remix-app/actions/modals.ts
  2. 10
      libs/remix-ui/app/src/lib/remix-app/components/modals/dialogs.tsx
  3. 49
      libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx
  4. 5
      libs/remix-ui/app/src/lib/remix-app/components/modals/modal-wrapper.tsx
  5. 26
      libs/remix-ui/app/src/lib/remix-app/components/modals/origin-warning.tsx
  6. 10
      libs/remix-ui/app/src/lib/remix-app/context/provider.tsx
  7. 10
      libs/remix-ui/app/src/lib/remix-app/reducer/modals.ts

@ -1,6 +1,6 @@
import { AppModal } from '../interface' import { AppModal } from '../interface'
export type ActionMap<M extends { [index: string]: any }> = { type ActionMap<M extends { [index: string]: any }> = {
[Key in keyof M]: M[Key] extends undefined [Key in keyof M]: M[Key] extends undefined
? { ? {
type: Key; type: Key;
@ -11,7 +11,7 @@ export type ActionMap<M extends { [index: string]: any }> = {
} }
} }
export const enum actionTypes { export const enum modalActionTypes {
setModal = 'SET_MODAL', setModal = 'SET_MODAL',
setToast = 'SET_TOAST', setToast = 'SET_TOAST',
handleHideModal = 'HANDLE_HIDE_MODAL', handleHideModal = 'HANDLE_HIDE_MODAL',
@ -19,10 +19,10 @@ export const enum actionTypes {
} }
type ModalPayload = { type ModalPayload = {
[actionTypes.setModal]: AppModal [modalActionTypes.setModal]: AppModal
[actionTypes.handleHideModal]: any [modalActionTypes.handleHideModal]: any
[actionTypes.setToast]: string [modalActionTypes.setToast]: string
[actionTypes.handleToaster]: any [modalActionTypes.handleToaster]: any
} }
export type ModalAction = ActionMap<ModalPayload>[keyof ActionMap< export type ModalAction = ActionMap<ModalPayload>[keyof ActionMap<

@ -8,16 +8,6 @@ const AppDialogs = () => {
const { modal, toast, alert, handleHideModal, handleToaster } = useDialogDispatchers() const { modal, toast, alert, handleHideModal, handleToaster } = useDialogDispatchers()
const { focusModal, focusToaster } = useDialogs() const { focusModal, focusToaster } = useDialogs()
const ok = (returnedValue) => {
console.log('ok', returnedValue)
}
useEffect(() => {
modal('test', 'Enter gist url', 'yes', ok, 'cancel', () => { }, ModalTypes.prompt, 'wss://remix.ethereum.org:8545')
toast('test toast')
// alert('fat error')
}, [])
return ( return (
<> <>
<ModalWrapper {...focusModal } handleHide={handleHideModal}></ModalWrapper> <ModalWrapper {...focusModal } handleHide={handleHideModal}></ModalWrapper>

@ -1,27 +1,40 @@
import React, { useContext, useEffect, useState } from 'react' import React, { useContext, useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
import { AppContext } from '../../context/context' import { AppContext } from '../../context/context'
import { useDialogDispatchers } from '../../context/provider'
const _paq = window._paq = window._paq || [] const _paq = window._paq = window._paq || []
const MatomoDialog = (props) => { const MatomoDialog = (props) => {
const { settings, showMatamo, appManager } = useContext(AppContext) const { settings, showMatamo, appManager } = useContext(AppContext)
const { modal } = useDialogDispatchers()
const [visible, setVisible] = useState<boolean>(props.hide) const [visible, setVisible] = useState<boolean>(props.hide)
useEffect(() => { useEffect(() => {
if (showMatamo) {
setVisible(true)
} else {
setVisible(false)
}
}, []) }, [])
const message = () => {
return (<><p>An Opt-in version of <a href="https://matomo.org" target="_blank" rel="noreferrer">Matomo</a>, an open source data analytics platform is being used to improve Remix IDE.</p>
<p>We realize that our users have sensitive information in their code and that their privacy - your privacy - must be protected.</p>
<p>All data collected through Matomo is stored on our own server - no data is ever given to third parties. Our analytics reports are public: <a href="https://matomo.ethereum.org/index.php?module=MultiSites&action=index&idSite=23&period=day&date=yesterday" target="_blank" rel="noreferrer">take a look</a>.</p>
<p>We do not collect nor store any personally identifiable information (PII).</p>
<p>For more info, see: <a href="https://medium.com/p/66ef69e14931/" target="_blank" rel="noreferrer">Matomo Analyitcs on Remix iDE</a>.</p>
<p>You can change your choice in the Settings panel anytime.</p></>)
}
useEffect(() => {
if (visible && showMatamo) {
console.log('show matomo')
modal('Help us to improve Remix IDE', message(), 'Accept', handleModalOkClick, 'Decline', declineModal)
}
}, [visible])
const declineModal = async () => { const declineModal = async () => {
settings.updateMatomoAnalyticsChoice(false) settings.updateMatomoAnalyticsChoice(false)
_paq.push(['optUserOut']) _paq.push(['optUserOut'])
appManager.call('walkthrough', 'start') appManager.call('walkthrough', 'start')
setVisible(false) setVisible(false)
} }
const hideModal = async () => {
setVisible(false)
}
const handleModalOkClick = async () => { const handleModalOkClick = async () => {
_paq.push(['forgetUserOptOut']) _paq.push(['forgetUserOptOut'])
// @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used // @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used
@ -30,22 +43,8 @@ const MatomoDialog = (props) => {
appManager.call('walkthrough', 'start') appManager.call('walkthrough', 'start')
setVisible(false) setVisible(false)
} }
return (<ModalDialog
handleHide={hideModal} return (<></>)
id="matomoDialog"
hide={!visible}
title="Help us to improve Remix IDE"
okLabel="Accept"
okFn={ handleModalOkClick }
cancelLabel="Decline"
cancelFn={declineModal}>
<p>An Opt-in version of <a href="https://matomo.org" target="_blank" rel="noreferrer">Matomo</a>, an open source data analytics platform is being used to improve Remix IDE.</p>
<p>We realize that our users have sensitive information in their code and that their privacy - your privacy - must be protected.</p>
<p>All data collected through Matomo is stored on our own server - no data is ever given to third parties. Our analytics reports are public: <a href="https://matomo.ethereum.org/index.php?module=MultiSites&action=index&idSite=23&period=day&date=yesterday" target="_blank" rel="noreferrer">take a look</a>.</p>
<p>We do not collect nor store any personally identifiable information (PII).</p>
<p>For more info, see: <a href="https://medium.com/p/66ef69e14931/" target="_blank" rel="noreferrer">Matomo Analyitcs on Remix iDE</a>.</p>
<p>You can change your choice in the Settings panel anytime.</p>
</ModalDialog>)
} }
export default MatomoDialog export default MatomoDialog

@ -45,10 +45,13 @@ const ModalWrapper = (props: ModalWrapperProps) => {
setState({ ...props }) setState({ ...props })
break break
} }
} else {
setState({ ...props })
} }
}, [props]) }, [props])
return ( return (
<ModalDialog id='appDialog' {...state} handleHide={props.handleHide} />) <ModalDialog id='appDialog' {...state} handleHide={props.handleHide} />
)
} }
export default ModalWrapper export default ModalWrapper

@ -1,9 +1,10 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog' import { ModalDialog } from '@remix-ui/modal-dialog'
import { useDialogDispatchers } from '../../context/provider'
const OriginWarning = () => { const OriginWarning = () => {
const [visible, setVisible] = useState<boolean>(true) const { alert } = useDialogDispatchers()
const [content, setContent] = useState<string>('') const [content, setContent] = useState<string>(null)
useEffect(() => { useEffect(() => {
// check the origin and warn message // check the origin and warn message
@ -20,24 +21,15 @@ const OriginWarning = () => {
This instance of Remix you are visiting WILL NOT BE UPDATED.\n This instance of Remix you are visiting WILL NOT BE UPDATED.\n
Please make a backup of your contracts and start using http://remix.ethereum.org`) Please make a backup of your contracts and start using http://remix.ethereum.org`)
} }
setVisible(content !== '')
}, []) }, [])
const closeModal = async () => { useEffect(() => {
setVisible(false) if (content) {
} alert(content)
const handleModalOkClick = async () => {
setVisible(false)
} }
return (<ModalDialog }, [content])
handleHide={closeModal}
id="appAlert" return (<></>)
hide={!visible}
title="Alert"
okLabel="Ok"
okFn={ handleModalOkClick }
cancelLabel=""
cancelFn={closeModal}>{content}</ModalDialog>)
} }
export default OriginWarning export default OriginWarning

@ -1,5 +1,5 @@
import React, { useReducer } from 'react' import React, { useReducer } from 'react'
import { actionTypes } from '../actions/modals' import { modalActionTypes } from '../actions/modals'
import { modalReducer } from '../reducer/modals' import { modalReducer } from '../reducer/modals'
import { ModalInitialState } from '../state/modals' import { ModalInitialState } from '../state/modals'
import { ModalTypes } from '../types' import { ModalTypes } from '../types'
@ -10,7 +10,7 @@ export const ModalProvider = ({ children = [], reducer = modalReducer, initialSt
const modal = (title: string, message: string | JSX.Element, okLabel: string, okFn: (value?:any) => void, cancelLabel?: string, cancelFn?: () => void, modalType?: ModalTypes, defaultValue?: string) => { const modal = (title: string, message: string | JSX.Element, okLabel: string, okFn: (value?:any) => void, cancelLabel?: string, cancelFn?: () => void, modalType?: ModalTypes, defaultValue?: string) => {
dispatch({ dispatch({
type: actionTypes.setModal, type: modalActionTypes.setModal,
payload: { title, message, okLabel, okFn, cancelLabel, cancelFn, modalType: modalType || ModalTypes.default, defaultValue: defaultValue } payload: { title, message, okLabel, okFn, cancelLabel, cancelFn, modalType: modalType || ModalTypes.default, defaultValue: defaultValue }
}) })
} }
@ -21,21 +21,21 @@ export const ModalProvider = ({ children = [], reducer = modalReducer, initialSt
const handleHideModal = () => { const handleHideModal = () => {
dispatch({ dispatch({
type: actionTypes.handleHideModal, type: modalActionTypes.handleHideModal,
payload: null payload: null
}) })
} }
const toast = (message: string) => { const toast = (message: string) => {
dispatch({ dispatch({
type: actionTypes.setToast, type: modalActionTypes.setToast,
payload: message payload: message
}) })
} }
const handleToaster = () => { const handleToaster = () => {
dispatch({ dispatch({
type: actionTypes.handleToaster, type: modalActionTypes.handleToaster,
payload: null payload: null
}) })
} }

@ -1,11 +1,11 @@
import { actionTypes, ModalAction } from '../actions/modals' import { modalActionTypes, ModalAction } from '../actions/modals'
import { ModalInitialState } from '../state/modals' import { ModalInitialState } from '../state/modals'
import { AppModal, ModalState } from '../interface' import { AppModal, ModalState } from '../interface'
export const modalReducer = (state: ModalState = ModalInitialState, action: ModalAction) => { export const modalReducer = (state: ModalState = ModalInitialState, action: ModalAction) => {
console.log(action) console.log(action)
switch (action.type) { switch (action.type) {
case actionTypes.setModal: { case modalActionTypes.setModal: {
console.log('set modal', action, Date.now()) console.log('set modal', action, Date.now())
let modalList:AppModal[] = state.modals let modalList:AppModal[] = state.modals
modalList.push(action.payload) modalList.push(action.payload)
@ -28,12 +28,12 @@ export const modalReducer = (state: ModalState = ModalInitialState, action: Moda
} }
return { ...state, modals: modalList } return { ...state, modals: modalList }
} }
case actionTypes.handleHideModal: case modalActionTypes.handleHideModal:
console.log('handle hid', JSON.stringify(state.modals)) console.log('handle hid', JSON.stringify(state.modals))
state.focusModal = { ...state.focusModal, hide: true, message: null } state.focusModal = { ...state.focusModal, hide: true, message: null }
return { ...state } return { ...state }
case actionTypes.setToast: case modalActionTypes.setToast:
state.toasters.push(action.payload) state.toasters.push(action.payload)
if (state.toasters.length > 0) { if (state.toasters.length > 0) {
const focus = state.toasters[0] const focus = state.toasters[0]
@ -42,7 +42,7 @@ export const modalReducer = (state: ModalState = ModalInitialState, action: Moda
} }
return { ...state } return { ...state }
case actionTypes.handleToaster: case modalActionTypes.handleToaster:
return { ...state, focusToaster: '' } return { ...state, focusToaster: '' }
} }
} }

Loading…
Cancel
Save