diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index 5a7c9b8dc0..9b39076918 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -319,7 +319,7 @@ class AppComponent { console.log("couldn't register iframe plugins", e.message) } await self.appManager.activatePlugin(['layout']) - await self.appManager.activatePlugin(['modal']) + await self.appManager.activatePlugin(['notification']) await self.appManager.activatePlugin(['editor']) await self.appManager.activatePlugin(['permissionhandler', 'theme', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter']) await self.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs']) diff --git a/apps/remix-ide/src/app/components/plugin-manager-component.js b/apps/remix-ide/src/app/components/plugin-manager-component.js index e86a62da92..72acd7cbf6 100644 --- a/apps/remix-ide/src/app/components/plugin-manager-component.js +++ b/apps/remix-ide/src/app/components/plugin-manager-component.js @@ -1,5 +1,4 @@ import { ViewPlugin } from '@remixproject/engine-web' -import { PluginManagerSettings } from './plugin-manager-settings' import React from 'react' // eslint-disable-line import ReactDOM from 'react-dom' import {RemixUiPluginManager} from '@remix-ui/plugin-manager' // eslint-disable-line @@ -24,7 +23,6 @@ class PluginManagerComponent extends ViewPlugin { super(profile) this.appManager = appManager this.engine = engine - this.pluginManagerSettings = new PluginManagerSettings() this.htmlElement = document.createElement('div') this.htmlElement.setAttribute('id', 'pluginManager') this.filter = '' @@ -90,7 +88,6 @@ class PluginManagerComponent extends ViewPlugin { ReactDOM.render( , this.htmlElement) } diff --git a/apps/remix-ide/src/app/components/plugin-manager-settings.js b/apps/remix-ide/src/app/components/plugin-manager-settings.js deleted file mode 100644 index bdd233ff15..0000000000 --- a/apps/remix-ide/src/app/components/plugin-manager-settings.js +++ /dev/null @@ -1,147 +0,0 @@ -const yo = require('yo-yo') -const csjs = require('csjs-inject') -const modalDialog = require('../ui/modaldialog') - -const css = csjs` -.remixui_permissions { - position: sticky; - bottom: 0; - display: flex; - justify-content: flex-end; - align-items: center; - padding: 5px 20px; -} -.permissions button { - padding: 2px 5px; - cursor: pointer; -} -.permissionForm h4 { - font-size: 1.3rem; - text-align: center; -} -.permissionForm h6 { - font-size: 1.1rem; -} -.permissionForm hr { - width: 80%; -} -.permissionKey { - display: flex; - justify-content: space-between; - align-items: center; -} -.permissionKey i { - cursor: pointer; -} -.checkbox { - display: flex; - align-items: center; -} -.checkbox label { - margin: 0; - font-size: 1rem; -} -` - -export class PluginManagerSettings { - constructor () { - const fromLocal = window.localStorage.getItem('plugins/permissions') - this.permissions = JSON.parse(fromLocal || '{}') - } - - openDialog () { - this.currentSetting = this.settings() - modalDialog('Plugin Manager Permissions', this.currentSetting, - { fn: () => this.onValidation() } - ) - } - - onValidation () { - const permissions = JSON.stringify(this.permissions) - window.localStorage.setItem('plugins/permissions', permissions) - } - - /** Clear one permission from a plugin */ - clearPersmission (from, to, method) { - // eslint-disable-next-line no-debugger - debugger - if (this.permissions[to] && this.permissions[to][method]) { - delete this.permissions[to][method][from] - if (Object.keys(this.permissions[to][method]).length === 0) { - delete this.permissions[to][method] - } - if (Object.keys(this.permissions[to]).length === 0) { - delete this.permissions[to] - } - yo.update(this.currentSetting, this.settings()) - } - } - - /** Clear all persmissions from a plugin */ - clearAllPersmission (to) { - // eslint-disable-next-line no-debugger - debugger - if (!this.permissions[to]) return - delete this.permissions[to] - yo.update(this.currentSetting, this.settings()) - } - - settings () { - const permissionByToPlugin = (toPlugin, funcObj) => { - const permissionByMethod = (methodName, fromPlugins) => { - const togglePermission = (fromPlugin) => { - this.permissions[toPlugin][methodName][fromPlugin].allow = !this.permissions[toPlugin][methodName][fromPlugin].allow - } - return Object.keys(fromPlugins).map(fromName => { - const fromPluginPermission = fromPlugins[fromName] - const checkbox = fromPluginPermission.allow - ? yo` togglePermission(fromName)} class="mr-2" type="checkbox" checked id="permission-checkbox-${toPlugin}-${methodName}-${toPlugin}" aria-describedby="module ${fromPluginPermission} asks permission for ${methodName}" />` - : yo` togglePermission(fromName)} class="mr-2" type="checkbox" id="permission-checkbox-${toPlugin}-${methodName}-${toPlugin}" aria-describedby="module ${fromPluginPermission} asks permission for ${methodName}" />` - return yo` -
-
- ${checkbox} - -
- -
- ` - }) - } - - const permissionsByFunctions = Object - .keys(funcObj) - .map(methodName => permissionByMethod(methodName, funcObj[methodName])) - - return yo` -
-
-

${toPlugin} permissions:

- -
- ${permissionsByFunctions} -
` - } - - const byToPlugin = Object - .keys(this.permissions) - .map(toPlugin => permissionByToPlugin(toPlugin, this.permissions[toPlugin])) - - const title = byToPlugin.length === 0 - ? yo`

No Permission requested yet.

` - : yo`

Current Permission settings

` - - return yo`
- ${title} -
- ${byToPlugin} -
` - } - - render () { - return yo` - ` - } -} diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index 14aa2d424c..7a1b7c375b 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -1,13 +1,11 @@ 'use strict' - -import yo from 'yo-yo' import async from 'async' import { Plugin } from '@remixproject/engine' import * as packageJson from '../../../../../package.json' import Registry from '../state/registry' import { EventEmitter } from 'events' import { RemixAppManager } from '../../../../../libs/remix-ui/plugin-manager/src/types' -const toaster = require('../ui/tooltip') +import { fileChangedToasterMsg } from '@remix-ui/helper' const helper = require('../../lib/helper.js') /* @@ -317,7 +315,7 @@ class FileManager extends Plugin { if (isFile) { if (newPathExists) { - this.call('modal', 'alert', { + this.call('notification', 'alert', { id: 'fileManagerAlert', message: 'File already exists' }) @@ -326,7 +324,7 @@ class FileManager extends Plugin { return provider.rename(oldPath, newPath, false) } else { if (newPathExists) { - this.call('modal', 'alert', { + this.call('notification', 'alert', { id: 'fileManagerAlert', message: 'Directory already exists' }) @@ -528,17 +526,7 @@ class FileManager extends Plugin { const required = this.appManager.isRequired(this.currentRequest.from) if (canCall && !required) { // inform the user about modification after permission is granted and even if permission was saved before - toaster(yo` -
- - - ${this.currentRequest.from} - - is modifying - ${path} - -
- `, '', { time: 3000 }) + this.call('notification','toast', fileChangedToasterMsg(this.currentRequest.from, path)) } } return await this._setFileInternal(path, content) @@ -778,12 +766,12 @@ class FileManager extends Plugin { helper.createNonClashingName(file, self._deps.filesProviders[fileProvider], (error, name) => { if (error) { - this.call('modal', 'alert', { + this.call('notification', 'alert', { id: 'fileManagerAlert', message: 'Unexpected error loading file ' + file + ': ' + error }) } else if (helper.checkSpecialChars(name)) { - this.call('modal', 'alert', { + this.call('notification', 'alert', { id: 'fileManagerAlert', message: 'Special characters are not allowed in file names.' }) diff --git a/apps/remix-ide/src/app/plugins/modal.tsx b/apps/remix-ide/src/app/plugins/modal.tsx index f5a855f0c2..d96e9b93f2 100644 --- a/apps/remix-ide/src/app/plugins/modal.tsx +++ b/apps/remix-ide/src/app/plugins/modal.tsx @@ -14,9 +14,9 @@ interface IModalApi { } const profile:LibraryProfile = { - name: 'modal', - displayName: 'Modal', - description: 'Modal', + name: 'notification', + displayName: 'Notification', + description: 'Displays notifications', methods: ['modal', 'alert', 'toast'] } diff --git a/libs/remix-ui/app/src/lib/remix-app/actions/modals.ts b/libs/remix-ui/app/src/lib/remix-app/actions/modals.ts index 95400ca77b..3a1788a8ad 100644 --- a/libs/remix-ui/app/src/lib/remix-app/actions/modals.ts +++ b/libs/remix-ui/app/src/lib/remix-app/actions/modals.ts @@ -21,7 +21,7 @@ export const enum modalActionTypes { type ModalPayload = { [modalActionTypes.setModal]: AppModal [modalActionTypes.handleHideModal]: any - [modalActionTypes.setToast]: string + [modalActionTypes.setToast]: string | JSX.Element [modalActionTypes.handleToaster]: any } diff --git a/libs/remix-ui/app/src/lib/remix-app/context/provider.tsx b/libs/remix-ui/app/src/lib/remix-app/context/provider.tsx index 61b98a4873..ab444470f6 100644 --- a/libs/remix-ui/app/src/lib/remix-app/context/provider.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/context/provider.tsx @@ -30,7 +30,7 @@ export const ModalProvider = ({ children = [], reducer = modalReducer, initialSt }) } - const toast = (message: string) => { + const toast = (message: string | JSX.Element) => { dispatch({ type: modalActionTypes.setToast, payload: message diff --git a/libs/remix-ui/app/src/lib/remix-app/interface/index.ts b/libs/remix-ui/app/src/lib/remix-app/interface/index.ts index 6546f22b0f..46aacf70b8 100644 --- a/libs/remix-ui/app/src/lib/remix-app/interface/index.ts +++ b/libs/remix-ui/app/src/lib/remix-app/interface/index.ts @@ -24,7 +24,7 @@ export interface AlertModal { export interface ModalState { modals: AppModal[], - toasters: string[], + toasters: string[] | JSX.Element[], focusModal: AppModal, - focusToaster: string + focusToaster: string | JSX.Element } diff --git a/libs/remix-ui/helper/src/index.ts b/libs/remix-ui/helper/src/index.ts index 961f14639b..0bd8695a4a 100644 --- a/libs/remix-ui/helper/src/index.ts +++ b/libs/remix-ui/helper/src/index.ts @@ -1 +1,2 @@ export * from './lib/remix-ui-helper' +export * from './lib/components' diff --git a/libs/remix-ui/helper/src/lib/components.tsx b/libs/remix-ui/helper/src/lib/components.tsx new file mode 100644 index 0000000000..361a4e1d87 --- /dev/null +++ b/libs/remix-ui/helper/src/lib/components.tsx @@ -0,0 +1,12 @@ +import React from 'react' + +export const fileChangedToasterMsg = (from: string, path: string) => ( +
+ + {from} + + is modifying + {path} + +
+) \ No newline at end of file diff --git a/libs/remix-ui/helper/tsconfig.json b/libs/remix-ui/helper/tsconfig.json index f4023e39ff..d52e31ad74 100644 --- a/libs/remix-ui/helper/tsconfig.json +++ b/libs/remix-ui/helper/tsconfig.json @@ -1,5 +1,11 @@ { "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, "files": [], "include": [], "references": [ diff --git a/libs/remix-ui/plugin-manager/src/lib/components/permissionsSettings.tsx b/libs/remix-ui/plugin-manager/src/lib/components/permissionsSettings.tsx index 690dadad8a..5936ec3f0d 100644 --- a/libs/remix-ui/plugin-manager/src/lib/components/permissionsSettings.tsx +++ b/libs/remix-ui/plugin-manager/src/lib/components/permissionsSettings.tsx @@ -5,11 +5,7 @@ import { ModalDialog } from '@remix-ui/modal-dialog' import useLocalStorage from '../custom-hooks/useLocalStorage' import { PluginPermissions } from '../../types' -interface PermissionSettingsProps { - pluginSettings: any -} - -function PermisssionsSettings ({ pluginSettings }: PermissionSettingsProps) { +function PermisssionsSettings () { const [modalVisibility, setModalVisibility] = useState(true) const [permissions, setPermissions] = useLocalStorage('plugins/permissions', {} as PluginPermissions) const [permissionCache, setpermissionCache] = useState() diff --git a/libs/remix-ui/plugin-manager/src/lib/components/rootView.tsx b/libs/remix-ui/plugin-manager/src/lib/components/rootView.tsx index 0e6d377146..1359e04ec3 100644 --- a/libs/remix-ui/plugin-manager/src/lib/components/rootView.tsx +++ b/libs/remix-ui/plugin-manager/src/lib/components/rootView.tsx @@ -7,7 +7,6 @@ import LocalPluginForm from './LocalPluginForm' interface RootViewProps { pluginComponent: PluginManagerComponent - pluginManagerSettings: PluginManagerSettings children: ReactNode } @@ -21,7 +20,7 @@ export interface pluginActivated { profile: Profile } -function RootView ({ pluginComponent, pluginManagerSettings, children }: RootViewProps) { +function RootView ({ pluginComponent, children }: RootViewProps) { const [visible, setVisible] = useState(true) const [filterPlugins, setFilterPlugin] = useState('') @@ -52,7 +51,7 @@ function RootView ({ pluginComponent, pluginManagerSettings, children }: RootVie {children} - + { +export const RemixUiPluginManager = ({ pluginComponent }: RemixUiPluginManagerProps) => { const [activeProfiles, setActiveProfiles] = useState(pluginComponent.activePlugins) const [inactiveProfiles, setinactiveProfiles] = useState(pluginComponent.inactivePlugins) return ( - +
void } export const Toaster = (props: ToasterProps) => { - const [state, setState] = useState({ + const [state, setState] = useState<{ + message: string | JSX.Element, + hide: boolean, + hiding: boolean, + timeOutId: any, + timeOut: number, + showModal: boolean, + showFullBtn: boolean + }>({ message: '', hide: true, hiding: false, timeOutId: null, timeOut: props.timeOut || 7000, - showModal: false + showModal: false, + showFullBtn: false }) useEffect(() => { @@ -29,9 +38,15 @@ export const Toaster = (props: ToasterProps) => { }, state.timeOut) setState(prevState => { - const shortTooltipText = props.message.length > 201 ? props.message.substring(0, 200) + '...' : props.message + if (typeof props.message === 'string' && (props.message.length > 201)) { + const shortTooltipText = props.message.substring(0, 200) + '...' - return { ...prevState, hide: false, hiding: false, timeOutId, message: shortTooltipText } + return { ...prevState, hide: false, hiding: false, timeOutId, message: shortTooltipText } + } else { + const shortTooltipText = props.message + + return { ...prevState, hide: false, hiding: false, timeOutId, message: shortTooltipText } + } }) } }, [props.message]) @@ -103,7 +118,7 @@ export const Toaster = (props: ToasterProps) => {
{ state.message } - { (props.message.length > 201) && } + { state.showFullBtn && }