fixed a bunch of plumbing with external persisted state of plugin manager

pull/1344/head
joseph izang 4 years ago
parent 3c951a9cbf
commit e6a0463e21
  1. 4
      apps/remix-ide/src/app/components/plugin-manager-component.js
  2. 19
      libs/remix-ui/plugin-manager/src/lib/components/ActivePluginCard.tsx
  3. 50
      libs/remix-ui/plugin-manager/src/lib/components/rootView.tsx
  4. 55
      libs/remix-ui/plugin-manager/src/pluginManagerStateMachine.ts

@ -53,7 +53,7 @@ class PluginManagerComponent extends ViewPlugin {
} }
triggerEngineEventListener () { triggerEngineEventListener () {
this.engine.event.on('onRegistration', () => this.getAndFilterPlugins()) this.engine.event.on('onRegistration', () => this.renderComponent())
} }
/** /**
@ -90,7 +90,7 @@ class PluginManagerComponent extends ViewPlugin {
debugger debugger
this.call('manager', 'deactivatePlugin', name) this.call('manager', 'deactivatePlugin', name)
_paq.push(['trackEvent', 'manager', 'deactivate', name]) _paq.push(['trackEvent', 'manager', 'deactivate', name])
this.getAndFilterPlugins() this.renderComponent()
} }
onActivation () { onActivation () {

@ -1,7 +1,6 @@
import { Profile } from '@remixproject/plugin-utils' import { Profile } from '@remixproject/plugin-utils'
import React, { useState } from 'react' import React, { useEffect, useState } from 'react'
import { RemoveActivatedPlugin } from '../../pluginManagerStateMachine' import { RemoveActivatedPlugin } from '../../pluginManagerStateMachine'
// import { RemoveActivatedPlugin } from '../../pluginManagerStateMachine'
import { PluginManagerComponent } from '../../types' import { PluginManagerComponent } from '../../types'
import '../remix-ui-plugin-manager.css' import '../remix-ui-plugin-manager.css'
interface PluginCardProps { interface PluginCardProps {
@ -10,7 +9,7 @@ interface PluginCardProps {
} }
pluginComponent: PluginManagerComponent pluginComponent: PluginManagerComponent
buttonText: string buttonText: string
reRender: () => void syncInactiveProfiles: () => void
} }
// eslint-disable-next-line no-empty-pattern // eslint-disable-next-line no-empty-pattern
@ -18,7 +17,7 @@ function ActivePluginCard ({
profile, profile,
pluginComponent, pluginComponent,
buttonText, buttonText,
reRender syncInactiveProfiles
}: PluginCardProps) { }: PluginCardProps) {
const [displayName] = useState<string>((profile.displayName) ? profile.displayName : profile.name) const [displayName] = useState<string>((profile.displayName) ? profile.displayName : profile.name)
const [docLink] = useState<JSX.Element>((profile.documentation) ? ( const [docLink] = useState<JSX.Element>((profile.documentation) ? (
@ -26,13 +25,16 @@ function ActivePluginCard ({
<i aria-hidden="true" className="fas fa-book"/> <i aria-hidden="true" className="fas fa-book"/>
</a> </a>
) : null) ) : null)
const [versionWarning] = useState<JSX.Element>((profile.version && profile.version.match(/\b(\w*alpha\w*)\b/g)) ? ( const [versionWarning] = useState<JSX.Element>((profile.version && profile.version.match(/\b(\w*alpha\w*)\b/g)) ? (
<small title="Version Alpha" className="remixui_versionWarning plugin-version">alpha</small> <small title="Version Alpha" className="remixui_versionWarning plugin-version">alpha</small>
) : (profile.version && profile.version.match(/\b(\w*beta\w*)\b/g)) ? ( ) : (profile.version && profile.version.match(/\b(\w*beta\w*)\b/g)) ? (
<small title="Version Beta" className="remixui_versionWarning plugin-version">beta</small> <small title="Version Beta" className="remixui_versionWarning plugin-version">beta</small>
) : null) ) : null)
// const [stateManager] = useState<PluginManagerStateMachine>(new PluginManagerStateMachine(pluginComponent)) const [triggerRefresh, setTriggerRefresh] = useState(false)
useEffect(() => {
}, [triggerRefresh])
return ( return (
<div className="list-group list-group-flush plugins-list-group" data-id="pluginManagerComponentActiveTile"> <div className="list-group list-group-flush plugins-list-group" data-id="pluginManagerComponentActiveTile">
@ -48,13 +50,10 @@ function ActivePluginCard ({
<button <button
onClick={() => { onClick={() => {
// pluginComponent.deactivateP(profile.name) // pluginComponent.deactivateP(profile.name)
console.log('calling pluginComponent.call directly...')
pluginComponent.call('manager', 'deactivatePlugin', profile.name) pluginComponent.call('manager', 'deactivatePlugin', profile.name)
console.log('called pluginComponent.call successfully')
pluginComponent._paq.push(['trackEvent', 'manager', 'deactivate', profile.name]) pluginComponent._paq.push(['trackEvent', 'manager', 'deactivate', profile.name])
console.log('matomo tracking captured for deactivation successfully')
RemoveActivatedPlugin(profile.name) RemoveActivatedPlugin(profile.name)
reRender() syncInactiveProfiles()
}} }}
className="btn btn-secondary btn-sm" className="btn btn-secondary btn-sm"
data-id={`pluginManagerComponentDeactivateButton${profile.name}`} data-id={`pluginManagerComponentDeactivateButton${profile.name}`}

@ -8,6 +8,7 @@ import PermisssionsSettings from './permissions/permissionsSettings'
import { Profile } from '@remixproject/plugin-utils' import { Profile } from '@remixproject/plugin-utils'
import ActivePluginCard from './ActivePluginCard' import ActivePluginCard from './ActivePluginCard'
import InactivePluginCard from './InactivePluginCard' import InactivePluginCard from './InactivePluginCard'
import { GetNewlyActivatedPlugins, PersistNewInactivesState } from '../../pluginManagerStateMachine'
const initialState: FormStateProps = { const initialState: FormStateProps = {
pname: 'test', pname: 'test',
@ -32,8 +33,7 @@ function RootView ({ pluginComponent }: RootViewProps) {
const [filterPlugins, setFilterPlugin] = useState('') const [filterPlugins, setFilterPlugin] = useState('')
const [activeP, setActiveP] = useState<Profile[]>([]) const [activeP, setActiveP] = useState<Profile[]>([])
const [inactiveP, setInactiveP] = useState<Profile[]>([]) const [inactiveP, setInactiveP] = useState<Profile[]>([])
// const [storagePlugins, setStoragePlugins] = useLocalStorage('newActivePlugins') const [triggerRefresh, setTriggerRefresh] = useState(false)
function pluginChangeHandler<P extends keyof FormStateProps> (formProps: P, value: FormStateProps[P]) { function pluginChangeHandler<P extends keyof FormStateProps> (formProps: P, value: FormStateProps[P]) {
setPlugin({ ...plugin, [formProps]: value }) setPlugin({ ...plugin, [formProps]: value })
} }
@ -46,10 +46,10 @@ function RootView ({ pluginComponent }: RootViewProps) {
} }
const closeModal = () => setVisible(true) const closeModal = () => setVisible(true)
// <-- End Modal Visibility States --> // <-- End Modal Visibility States -->
// eslint-disable-next-line react-hooks/exhaustive-deps
const reRender = () => { const syncInactiveProfiles = () => {
pluginComponent.getAndFilterPlugins() PersistNewInactivesState(inactiveP)
console.log('Called rerender after deactivating a plugin') setTriggerRefresh(true)
} }
useEffect(() => { useEffect(() => {
@ -61,12 +61,44 @@ function RootView ({ pluginComponent }: RootViewProps) {
if (pluginComponent.activePlugins && pluginComponent.activePlugins.length) { if (pluginComponent.activePlugins && pluginComponent.activePlugins.length) {
setActiveP(pluginComponent.activePlugins) setActiveP(pluginComponent.activePlugins)
} }
// if (pluginComponent.inactivePlugins && pluginComponent.inactivePlugins.length) {
// setInactiveP(pluginComponent.inactivePlugins)
// }
const validInactiveProfiles: Profile[] = JSON.parse(window.localStorage.getItem('updatedInactives'))
if (validInactiveProfiles && validInactiveProfiles.length) {
if (inactiveP.length > validInactiveProfiles.length) {
setInactiveP(validInactiveProfiles)
}
}
if (pluginComponent.inactivePlugins && pluginComponent.inactivePlugins.length) { if (pluginComponent.inactivePlugins && pluginComponent.inactivePlugins.length) {
setInactiveP(pluginComponent.inactivePlugins) setInactiveP(pluginComponent.inactivePlugins)
} }
console.log('contents of appManager', pluginComponent.appManager)
}, [pluginComponent.activePlugins, pluginComponent.inactivePlugins, activeP, inactiveP, pluginComponent.activeProfiles, pluginComponent]) }, [pluginComponent.activePlugins, pluginComponent.inactivePlugins, activeP, inactiveP, pluginComponent.activeProfiles, pluginComponent])
useEffect(() => {
if (activeP.length === 0) {
const activeProfiles = GetNewlyActivatedPlugins()
if (activeProfiles !== null && activeProfiles.length) {
setActiveP(activeProfiles)
} else {
setActiveP(pluginComponent.activePlugins)
}
}
}, [activeP, pluginComponent.activePlugins, syncInactiveProfiles])
useEffect(() => {
syncInactiveProfiles()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [inactiveP, triggerRefresh])
useEffect(() => {
const validInactiveProfiles: Profile[] = JSON.parse(window.localStorage.getItem('updatedInactives'))
if (validInactiveProfiles && validInactiveProfiles.length &&
inactiveP.length > validInactiveProfiles.length) {
setInactiveP(validInactiveProfiles)
}
}, [inactiveP, triggerRefresh])
return ( return (
<Fragment> <Fragment>
<form id="local-plugin-form"> <form id="local-plugin-form">
@ -224,14 +256,14 @@ function RootView ({ pluginComponent }: RootViewProps) {
</button> </button>
</header> </header>
<section data-id="pluginManagerComponentPluginManagerSection"> <section data-id="pluginManagerComponentPluginManagerSection">
{activeP && <Fragment> {(activeP && activeP.length > 0) && <Fragment>
<ModuleHeading headingLabel="Active Modules" count={activeP.length} /> <ModuleHeading headingLabel="Active Modules" count={activeP.length} />
{activeP.map((profile) => ( {activeP.map((profile) => (
<ActivePluginCard <ActivePluginCard
buttonText="Deactivate" buttonText="Deactivate"
key={profile.name} key={profile.name}
profile={profile} profile={profile}
reRender={reRender} syncInactiveProfiles={syncInactiveProfiles}
pluginComponent={pluginComponent} pluginComponent={pluginComponent}
/> />
))} ))}

@ -42,7 +42,7 @@ export async function PersistActivatedPlugin (pluginComponent: PluginManagerComp
if (newPlugin) { if (newPlugin) {
if (defaultActivatedPlugins.includes(newPlugin.name) === false) { if (defaultActivatedPlugins.includes(newPlugin.name) === false) {
// if this is true then we are sure that the profile name is in localStorage/workspace // if this is true then we are sure that the profile name is in localStorage/workspace
if (activatedPlugins.length > 0 && !activatedPlugins.includes(newPlugin)) { if (activatedPlugins && activatedPlugins.length && !activatedPlugins.includes(newPlugin)) {
await FetchAndPersistPlugin(pluginComponent, newPlugin, activatedPlugins) await FetchAndPersistPlugin(pluginComponent, newPlugin, activatedPlugins)
localStorage.setItem('newActivePlugins', JSON.stringify(activatedPlugins)) localStorage.setItem('newActivePlugins', JSON.stringify(activatedPlugins))
} else { } else {
@ -53,6 +53,44 @@ export async function PersistActivatedPlugin (pluginComponent: PluginManagerComp
} }
} }
/**
* Update the list of inactive plugin profiles filtering based on a predetermined
* filter pipeline
* @param deactivatedPlugin plugin profile to be deactivated
* @param pluginComponent Plugin manager class which is the context for all operations
* @returns {Array} array of inactives
*/
export async function UpdateInactivePluginList (deactivatedPlugin: Profile, pluginComponent: PluginManagerComponent) {
const activated: Profile[] = JSON.parse(window.localStorage.getItem('newActivePlugins'))
const isFiltered = (profile) => (profile.displayName ? profile.displayName : profile.name)
.toLowerCase().includes(deactivatedPlugin.name)
const isNotActivated = (profile) => activated.includes(profile)
const isNotRequired = (profile) => !pluginComponent.appManager.isRequired(profile.name)
const isNotDependent = (profile) => !pluginComponent.appManager.isDependent(profile.name)
const isNotHome = (profile) => profile.name !== 'home'
const sortByName = (profileA, profileB) => {
const nameA = ((profileA.displayName) ? profileA.displayName : profileA.name).toUpperCase()
const nameB = ((profileB.displayName) ? profileB.displayName : profileB.name).toUpperCase()
return (nameA < nameB) ? -1 : (nameA > nameB) ? 1 : 0
}
const tempArray = pluginComponent.appManager.getAll()
.filter(isFiltered)
.filter(isNotActivated)
.filter(isNotRequired)
.filter(isNotDependent)
.filter(isNotHome)
.sort(sortByName)
return tempArray
}
export function GetNewlyActivatedPlugins () {
const profiles = JSON.parse(window.localStorage.getItem('newActivePlugins'))
if (profiles && profiles.length > 0) {
return profiles
}
return profiles
}
async function FetchAndPersistPlugin (pluginComponent: PluginManagerComponent, newPlugin: Profile<any>, newlyActivatedPlugins: Profile<any>[]) { async function FetchAndPersistPlugin (pluginComponent: PluginManagerComponent, newPlugin: Profile<any>, newlyActivatedPlugins: Profile<any>[]) {
try { try {
const targetProfile = await pluginComponent.appManager.getProfile(newPlugin.name) const targetProfile = await pluginComponent.appManager.getProfile(newPlugin.name)
@ -67,9 +105,18 @@ async function FetchAndPersistPlugin (pluginComponent: PluginManagerComponent, n
* @param pluginName Name of plugin profile to be removed * @param pluginName Name of plugin profile to be removed
*/ */
export function RemoveActivatedPlugin (pluginName: string) { export function RemoveActivatedPlugin (pluginName: string) {
// eslint-disable-next-line no-debugger
debugger
const getWorkspacePlugins = JSON.parse(localStorage.getItem('newActivePlugins')) const getWorkspacePlugins = JSON.parse(localStorage.getItem('newActivePlugins'))
const removeExisting = getWorkspacePlugins.filter(target => target.name === pluginName) const removeExisting = getWorkspacePlugins.filter(target => target.name !== pluginName)
localStorage.setItem('newActivePlugins', JSON.stringify(removeExisting)) localStorage.setItem('newActivePlugins', JSON.stringify(removeExisting))
} }
/**
* gets the latest list of inactive plugin profiles and persist them
* in local storage
* @param inactivesList Array of inactive plugin profiles
*/
export function PersistNewInactivesState (inactivesList: Profile[]) {
if (inactivesList && inactivesList.length) {
localStorage.setItem('updatedInactives', JSON.stringify(inactivesList))
}
}

Loading…
Cancel
Save