From a0280d86e9f568732a886e1b2e3fdc970d3a01b7 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Wed, 2 Jan 2019 18:35:36 +0100 Subject: [PATCH 01/11] Go back to using FormNestedFoot in Nested Array Fields --- .../vulcan-forms/lib/components/FormNestedArray.jsx | 13 +++++-------- .../vulcan-forms/lib/components/FormNestedFoot.jsx | 4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/vulcan-forms/lib/components/FormNestedArray.jsx b/packages/vulcan-forms/lib/components/FormNestedArray.jsx index 96ab98528..911309f6a 100644 --- a/packages/vulcan-forms/lib/components/FormNestedArray.jsx +++ b/packages/vulcan-forms/lib/components/FormNestedArray.jsx @@ -97,15 +97,12 @@ class FormNestedArray extends PureComponent { ) ), (!maxCount || arrayLength < maxCount) && ( - - - + addItem={this.addItem} + label={this.props.label} + className="form-nested-foot" + /> ), hasErrors ? ( ( - +const FormNestedFoot = ({ addItem }) => ( + ); From 45e5e19861159f5016ae2919e1da0fce1cc907ff Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Tue, 8 Jan 2019 16:15:19 +0100 Subject: [PATCH 02/11] Add LayoutName to the Routes Debug dashboard --- .../vulcan-debug/lib/components/Routes.jsx | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/packages/vulcan-debug/lib/components/Routes.jsx b/packages/vulcan-debug/lib/components/Routes.jsx index a86b79e9a..ff538fef3 100644 --- a/packages/vulcan-debug/lib/components/Routes.jsx +++ b/packages/vulcan-debug/lib/components/Routes.jsx @@ -1,26 +1,31 @@ import React from 'react'; -import { registerComponent, Components, Routes } from 'meteor/vulcan:lib'; -import { Link } from 'react-router'; +import {registerComponent, Components, Routes} from 'meteor/vulcan:lib'; +import {Link} from 'react-router'; -const RoutePath = ({ document }) => - {document.path}; +const RoutePath = ({document}) => ( + {document.path} +); -const RoutesDashboard = props => -
- -
; +const RoutesDashboard = props => { + return ( +
+ +
+ ); +}; -registerComponent('Routes', RoutesDashboard); \ No newline at end of file +registerComponent('Routes', RoutesDashboard); From be42d6740f9916a63fcd7e90e3e0fd4059b56898 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Tue, 8 Jan 2019 16:21:26 +0100 Subject: [PATCH 03/11] rename AdminLayout to DebugLayout in the debug package --- .../vulcan-debug/lib/components/AdminLayout.jsx | 10 ---------- .../vulcan-debug/lib/components/DebugLayout.jsx | 10 ++++++++++ packages/vulcan-debug/lib/modules/components.js | 2 +- packages/vulcan-debug/lib/modules/routes.js | 16 ++++++++-------- 4 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 packages/vulcan-debug/lib/components/AdminLayout.jsx create mode 100644 packages/vulcan-debug/lib/components/DebugLayout.jsx diff --git a/packages/vulcan-debug/lib/components/AdminLayout.jsx b/packages/vulcan-debug/lib/components/AdminLayout.jsx deleted file mode 100644 index 238b7dfc4..000000000 --- a/packages/vulcan-debug/lib/components/AdminLayout.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import { Components, registerComponent } from 'meteor/vulcan:lib'; - -const adminStyles = { - padding: '20px' -}; - -const AdminLayout = props =>
{props.children}
; - -registerComponent('AdminLayout', AdminLayout); \ No newline at end of file diff --git a/packages/vulcan-debug/lib/components/DebugLayout.jsx b/packages/vulcan-debug/lib/components/DebugLayout.jsx new file mode 100644 index 000000000..872619e53 --- /dev/null +++ b/packages/vulcan-debug/lib/components/DebugLayout.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { Components, registerComponent } from 'meteor/vulcan:lib'; + +const debugStyles = { + padding: '20px' +}; + +const DebugLayout = props =>
{props.children}
; + +registerComponent('DebugLayout', DebugLayout); diff --git a/packages/vulcan-debug/lib/modules/components.js b/packages/vulcan-debug/lib/modules/components.js index 0dcc47be3..bd8da2a7e 100644 --- a/packages/vulcan-debug/lib/modules/components.js +++ b/packages/vulcan-debug/lib/modules/components.js @@ -1,4 +1,4 @@ -import '../components/AdminLayout.jsx'; +import '../components/DebugLayout.jsx'; import '../components/Emails.jsx'; import '../components/Groups.jsx'; diff --git a/packages/vulcan-debug/lib/modules/routes.js b/packages/vulcan-debug/lib/modules/routes.js index c4e7957af..b75f9e938 100644 --- a/packages/vulcan-debug/lib/modules/routes.js +++ b/packages/vulcan-debug/lib/modules/routes.js @@ -2,13 +2,13 @@ import { addRoute, getDynamicComponent } from 'meteor/vulcan:lib'; addRoute([ // {name: 'cheatsheet', path: '/cheatsheet', component: import('./components/Cheatsheet.jsx')}, - { name: 'debug', path: '/debug', componentName: 'DebugDashboard', layoutName: 'AdminLayout' }, - { name: 'debugGroups', path: '/debug/groups', component: () => getDynamicComponent(import('../components/Groups.jsx')), layoutName: 'AdminLayout' }, - { name: 'debugSettings', path: '/debug/settings', componentName: 'Settings', layoutName: 'AdminLayout' }, - { name: 'debugCallbacks', path: '/debug/callbacks', componentName: 'Callbacks', layoutName: 'AdminLayout' }, + { name: 'debug', path: '/debug', componentName: 'DebugDashboard', layoutName: 'DebugLayout' }, + { name: 'debugGroups', path: '/debug/groups', component: () => getDynamicComponent(import('../components/Groups.jsx')), layoutName: 'DebugLayout' }, + { name: 'debugSettings', path: '/debug/settings', componentName: 'Settings', layoutName: 'DebugLayout' }, + { name: 'debugCallbacks', path: '/debug/callbacks', componentName: 'Callbacks', layoutName: 'DebugLayout' }, // {name: 'emails', path: '/emails', component: () => getDynamicComponent(import('./components/Emails.jsx'))}, - { name: 'debugEmails', path: '/debug/emails', componentName: 'Emails', layoutName: 'AdminLayout' }, - { name: 'debugRoutes', path: '/debug/routes', componentName: 'Routes', layoutName: 'AdminLayout' }, - { name: 'debugComponents', path: '/debug/components', componentName: 'Components', layoutName: 'AdminLayout' }, - { name: 'debugI18n', path: '/debug/i18n', componentName: 'I18n', layoutName: 'AdminLayout' }, + { name: 'debugEmails', path: '/debug/emails', componentName: 'Emails', layoutName: 'DebugLayout' }, + { name: 'debugRoutes', path: '/debug/routes', componentName: 'Routes', layoutName: 'DebugLayout' }, + { name: 'debugComponents', path: '/debug/components', componentName: 'Components', layoutName: 'DebugLayout' }, + { name: 'debugI18n', path: '/debug/i18n', componentName: 'I18n', layoutName: 'DebugLayout' }, ]); From 1da5d5d4f238783acc6e00c44b360f6391f29d63 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Tue, 8 Jan 2019 16:22:14 +0100 Subject: [PATCH 04/11] create AdminLayout in vulcan:admin --- .../lib/components/AdminLayout.jsx | 44 +++++++++++++++++++ packages/vulcan-admin/lib/modules/index.js | 1 + packages/vulcan-admin/lib/modules/routes.js | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 packages/vulcan-admin/lib/components/AdminLayout.jsx diff --git a/packages/vulcan-admin/lib/components/AdminLayout.jsx b/packages/vulcan-admin/lib/components/AdminLayout.jsx new file mode 100644 index 000000000..f01785d96 --- /dev/null +++ b/packages/vulcan-admin/lib/components/AdminLayout.jsx @@ -0,0 +1,44 @@ +/** + * @Author: Apollinaire Lecocq + * @Date: 08-01-19 + * @Last modified by: apollinaire + * @Last modified time: 08-01-19 + */ +import React from 'react'; +import { + registerComponent, + Components, + withCurrentUser, +} from 'meteor/vulcan:core'; + +/** + * A simple component that renders the existing layout and checks wether the currentUser is an admin or not. + */ + +class AdminLayout extends React.PureComponent { + renderWithRestrictedAccess(children, currentUser) { + // while the currentUser is loading, don't render anything. + if (currentUser && currentUser.loading) { + return null; + } //if the currentUser is an admin, then render the children + else if (currentUser && currentUser.isAdmin) { + return children; + } // for every other case (just a member or not logged), render the 404 message + return ; + } + + render() { + const {currentUser, children} = this.props; + return ( + + {this.renderWithRestrictedAccess(children, currentUser)} + + ); + } +} + +registerComponent({ + name: 'AdminLayout', + component: AdminLayout, + hocs: [withCurrentUser], +}); diff --git a/packages/vulcan-admin/lib/modules/index.js b/packages/vulcan-admin/lib/modules/index.js index 9a851d3e1..895e5bc7c 100644 --- a/packages/vulcan-admin/lib/modules/index.js +++ b/packages/vulcan-admin/lib/modules/index.js @@ -1,3 +1,4 @@ import './fragments.js'; import './routes.js'; import './i18n.js'; +import '../components/AdminLayout'; diff --git a/packages/vulcan-admin/lib/modules/routes.js b/packages/vulcan-admin/lib/modules/routes.js index b71519605..ad80fae78 100644 --- a/packages/vulcan-admin/lib/modules/routes.js +++ b/packages/vulcan-admin/lib/modules/routes.js @@ -1,5 +1,5 @@ import { addRoute, getDynamicComponent } from 'meteor/vulcan:core'; import React from 'react'; -addRoute({ name: 'admin', path: '/admin', component: () => getDynamicComponent(import('../components/AdminHome.jsx'))}); +addRoute({ name: 'admin', path: '/admin', component: () => getDynamicComponent(import('../components/AdminHome.jsx')), layoutName: 'AdminLayout'}); addRoute({ name: 'admin2', path: '/admin/users', component: () => getDynamicComponent(import('../components/AdminHome.jsx'))}); From e0ed139215063a89e45dc155e532d3e4dad0f4f2 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Tue, 8 Jan 2019 18:38:20 +0100 Subject: [PATCH 05/11] currentUser.loading -> currentUserLoading --- packages/vulcan-admin/lib/components/AdminLayout.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vulcan-admin/lib/components/AdminLayout.jsx b/packages/vulcan-admin/lib/components/AdminLayout.jsx index f01785d96..b3685f5a8 100644 --- a/packages/vulcan-admin/lib/components/AdminLayout.jsx +++ b/packages/vulcan-admin/lib/components/AdminLayout.jsx @@ -18,7 +18,7 @@ import { class AdminLayout extends React.PureComponent { renderWithRestrictedAccess(children, currentUser) { // while the currentUser is loading, don't render anything. - if (currentUser && currentUser.loading) { + if (currentUserLoading) { return null; } //if the currentUser is an admin, then render the children else if (currentUser && currentUser.isAdmin) { From 70581a103608fad46fbc953ee0fe070f5cc5fa80 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Tue, 8 Jan 2019 18:40:02 +0100 Subject: [PATCH 06/11] automatic prettier --- packages/vulcan-admin/lib/modules/routes.js | 15 ++++-- packages/vulcan-debug/lib/modules/routes.js | 58 +++++++++++++++++---- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/packages/vulcan-admin/lib/modules/routes.js b/packages/vulcan-admin/lib/modules/routes.js index ad80fae78..725b61ff0 100644 --- a/packages/vulcan-admin/lib/modules/routes.js +++ b/packages/vulcan-admin/lib/modules/routes.js @@ -1,5 +1,14 @@ -import { addRoute, getDynamicComponent } from 'meteor/vulcan:core'; +import {addRoute, getDynamicComponent} from 'meteor/vulcan:core'; import React from 'react'; -addRoute({ name: 'admin', path: '/admin', component: () => getDynamicComponent(import('../components/AdminHome.jsx')), layoutName: 'AdminLayout'}); -addRoute({ name: 'admin2', path: '/admin/users', component: () => getDynamicComponent(import('../components/AdminHome.jsx'))}); +addRoute({ + name: 'admin', + path: '/admin', + component: () => getDynamicComponent(import('../components/AdminHome.jsx')), + layoutName: 'AdminLayout', +}); +addRoute({ + name: 'admin2', + path: '/admin/users', + component: () => getDynamicComponent(import('../components/AdminHome.jsx')), +}); diff --git a/packages/vulcan-debug/lib/modules/routes.js b/packages/vulcan-debug/lib/modules/routes.js index b75f9e938..d5ef99c88 100644 --- a/packages/vulcan-debug/lib/modules/routes.js +++ b/packages/vulcan-debug/lib/modules/routes.js @@ -1,14 +1,54 @@ -import { addRoute, getDynamicComponent } from 'meteor/vulcan:lib'; +import {addRoute, getDynamicComponent} from 'meteor/vulcan:lib'; addRoute([ // {name: 'cheatsheet', path: '/cheatsheet', component: import('./components/Cheatsheet.jsx')}, - { name: 'debug', path: '/debug', componentName: 'DebugDashboard', layoutName: 'DebugLayout' }, - { name: 'debugGroups', path: '/debug/groups', component: () => getDynamicComponent(import('../components/Groups.jsx')), layoutName: 'DebugLayout' }, - { name: 'debugSettings', path: '/debug/settings', componentName: 'Settings', layoutName: 'DebugLayout' }, - { name: 'debugCallbacks', path: '/debug/callbacks', componentName: 'Callbacks', layoutName: 'DebugLayout' }, + { + name: 'debug', + path: '/debug', + componentName: 'DebugDashboard', + layoutName: 'DebugLayout', + }, + { + name: 'debugGroups', + path: '/debug/groups', + component: () => getDynamicComponent(import('../components/Groups.jsx')), + layoutName: 'DebugLayout', + }, + { + name: 'debugSettings', + path: '/debug/settings', + componentName: 'Settings', + layoutName: 'DebugLayout', + }, + { + name: 'debugCallbacks', + path: '/debug/callbacks', + componentName: 'Callbacks', + layoutName: 'DebugLayout', + }, // {name: 'emails', path: '/emails', component: () => getDynamicComponent(import('./components/Emails.jsx'))}, - { name: 'debugEmails', path: '/debug/emails', componentName: 'Emails', layoutName: 'DebugLayout' }, - { name: 'debugRoutes', path: '/debug/routes', componentName: 'Routes', layoutName: 'DebugLayout' }, - { name: 'debugComponents', path: '/debug/components', componentName: 'Components', layoutName: 'DebugLayout' }, - { name: 'debugI18n', path: '/debug/i18n', componentName: 'I18n', layoutName: 'DebugLayout' }, + { + name: 'debugEmails', + path: '/debug/emails', + componentName: 'Emails', + layoutName: 'DebugLayout', + }, + { + name: 'debugRoutes', + path: '/debug/routes', + componentName: 'Routes', + layoutName: 'DebugLayout', + }, + { + name: 'debugComponents', + path: '/debug/components', + componentName: 'Components', + layoutName: 'DebugLayout', + }, + { + name: 'debugI18n', + path: '/debug/i18n', + componentName: 'I18n', + layoutName: 'DebugLayout', + }, ]); From 74e41dd97dd250ea3aa2d70d8c1a799e65c5e025 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Wed, 9 Jan 2019 11:29:25 +0100 Subject: [PATCH 07/11] use withAccess in AdminLayout --- .../lib/components/AdminLayout.jsx | 43 +++++++------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/packages/vulcan-admin/lib/components/AdminLayout.jsx b/packages/vulcan-admin/lib/components/AdminLayout.jsx index b3685f5a8..3062f17d5 100644 --- a/packages/vulcan-admin/lib/components/AdminLayout.jsx +++ b/packages/vulcan-admin/lib/components/AdminLayout.jsx @@ -2,43 +2,32 @@ * @Author: Apollinaire Lecocq * @Date: 08-01-19 * @Last modified by: apollinaire - * @Last modified time: 08-01-19 + * @Last modified time: 09-01-19 */ import React from 'react'; -import { - registerComponent, - Components, - withCurrentUser, -} from 'meteor/vulcan:core'; +import {registerComponent, Components, withAccess} from 'meteor/vulcan:core'; + +// we need a component to wrap the `withAccess` hoc around something +function EmptyComponent({children}) { + return children; +} +EmptyComponent.displayName = 'EmptyComponent'; + +const RestrictToAdmins = withAccess({groups: ['admins']})(EmptyComponent); /** * A simple component that renders the existing layout and checks wether the currentUser is an admin or not. */ -class AdminLayout extends React.PureComponent { - renderWithRestrictedAccess(children, currentUser) { - // while the currentUser is loading, don't render anything. - if (currentUserLoading) { - return null; - } //if the currentUser is an admin, then render the children - else if (currentUser && currentUser.isAdmin) { - return children; - } // for every other case (just a member or not logged), render the 404 message - return ; - } - - render() { - const {currentUser, children} = this.props; - return ( - - {this.renderWithRestrictedAccess(children, currentUser)} - - ); - } +function AdminLayout({children}) { + return ( + + {children} + + ); } registerComponent({ name: 'AdminLayout', component: AdminLayout, - hocs: [withCurrentUser], }); From 1e6e6f88f3bce3bdcfb60c3fbafe7458e1a08c57 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Thu, 10 Jan 2019 14:23:50 +0100 Subject: [PATCH 08/11] Wrap ErrorCatcher with `withSiteData` This way you can add multiple error catchers in your react tree. My use case is adding one in the Modal component, so that when you add a buggy thing in the modal it's caught here and the user can exit the modal and the rest of the app is still rendered. --- packages/vulcan-core/lib/modules/components/App.jsx | 6 ++---- packages/vulcan-core/lib/modules/components/Dummy.jsx | 10 ++++++++++ packages/vulcan-core/lib/modules/index.js | 2 ++ packages/vulcan-errors/lib/components/ErrorCatcher.jsx | 4 ++-- 4 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 packages/vulcan-core/lib/modules/components/Dummy.jsx diff --git a/packages/vulcan-core/lib/modules/components/App.jsx b/packages/vulcan-core/lib/modules/components/App.jsx index 5bc556d68..e256bcb3e 100644 --- a/packages/vulcan-core/lib/modules/components/App.jsx +++ b/packages/vulcan-core/lib/modules/components/App.jsx @@ -17,8 +17,6 @@ import { withApollo } from 'react-apollo'; import { withCookies } from 'react-cookie'; import moment from 'moment'; -const DummyErrorCatcher = ({ children }) => children; - class App extends PureComponent { constructor(props) { super(props); @@ -114,7 +112,7 @@ class App extends PureComponent { const LayoutComponent = currentRoute.layoutName ? Components[currentRoute.layoutName] : Components.Layout; // if defined, use ErrorCatcher component to wrap layout contents - const ErrorCatcher = Components.ErrorCatcher ? Components.ErrorCatcher : DummyErrorCatcher; + const ErrorCatcher = Components.ErrorCatcher ? Components.ErrorCatcher : Components.Dummy; return ( @@ -125,7 +123,7 @@ class App extends PureComponent { {this.props.currentUserLoading ? ( ) : this.props.children ? ( - {this.props.children} + {this.props.children} ) : ( )} diff --git a/packages/vulcan-core/lib/modules/components/Dummy.jsx b/packages/vulcan-core/lib/modules/components/Dummy.jsx new file mode 100644 index 000000000..65f64de54 --- /dev/null +++ b/packages/vulcan-core/lib/modules/components/Dummy.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import {registerComponent} from 'meteor/vulcan:lib'; + +function Dummy({children}) { + return children; +} +Dummy.displayName = 'Dummy'; + +registerComponent({name: 'Dummy', component: Dummy}); +export default Dummy; diff --git a/packages/vulcan-core/lib/modules/index.js b/packages/vulcan-core/lib/modules/index.js index abc5165a6..e6e0cd47a 100644 --- a/packages/vulcan-core/lib/modules/index.js +++ b/packages/vulcan-core/lib/modules/index.js @@ -24,6 +24,7 @@ export { default as Flash } from './components/Flash.jsx'; export { default as HelloWorld } from './components/HelloWorld.jsx'; export { default as Welcome } from './components/Welcome.jsx'; export { default as RouterHook } from './components/RouterHook.jsx'; +export { default as Dummy } from './components/Dummy.jsx'; export { default as withAccess } from './containers/withAccess.js'; export { default as withMessages } from './containers/withMessages.js'; @@ -35,6 +36,7 @@ export { default as withDelete } from './containers/withDelete.js'; export { default as withCurrentUser } from './containers/withCurrentUser.js'; export { default as withMutation } from './containers/withMutation.js'; export { default as withUpsert } from './containers/withUpsert.js'; +export { default as withSiteData } from './containers/withSiteData.js'; export { default as withComponents } from './containers/withComponents'; diff --git a/packages/vulcan-errors/lib/components/ErrorCatcher.jsx b/packages/vulcan-errors/lib/components/ErrorCatcher.jsx index b8be2f322..c542571bc 100644 --- a/packages/vulcan-errors/lib/components/ErrorCatcher.jsx +++ b/packages/vulcan-errors/lib/components/ErrorCatcher.jsx @@ -10,7 +10,7 @@ Usage: */ -import { Components, registerComponent, withCurrentUser } from 'meteor/vulcan:core'; +import { Components, registerComponent, withCurrentUser, withSiteData } from 'meteor/vulcan:core'; import React, { Component } from 'react'; import { Errors } from '../modules/errors.js'; @@ -43,4 +43,4 @@ class ErrorCatcher extends Component { } } -registerComponent('ErrorCatcher', ErrorCatcher, withCurrentUser); +registerComponent('ErrorCatcher', ErrorCatcher, withCurrentUser, withSiteData); From ce8e29fc5b1f10dcabee50280cf42c0dfb8a3014 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Thu, 10 Jan 2019 14:28:23 +0100 Subject: [PATCH 09/11] Rewrite AdminLayout to use new Dummy component --- packages/vulcan-admin/lib/components/AdminLayout.jsx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/vulcan-admin/lib/components/AdminLayout.jsx b/packages/vulcan-admin/lib/components/AdminLayout.jsx index 3062f17d5..98d7cf0bf 100644 --- a/packages/vulcan-admin/lib/components/AdminLayout.jsx +++ b/packages/vulcan-admin/lib/components/AdminLayout.jsx @@ -2,18 +2,12 @@ * @Author: Apollinaire Lecocq * @Date: 08-01-19 * @Last modified by: apollinaire - * @Last modified time: 09-01-19 + * @Last modified time: 10-01-19 */ import React from 'react'; -import {registerComponent, Components, withAccess} from 'meteor/vulcan:core'; +import {registerComponent, Components, withAccess, Dummy} from 'meteor/vulcan:core'; -// we need a component to wrap the `withAccess` hoc around something -function EmptyComponent({children}) { - return children; -} -EmptyComponent.displayName = 'EmptyComponent'; - -const RestrictToAdmins = withAccess({groups: ['admins']})(EmptyComponent); +const RestrictToAdmins = withAccess({groups: ['admins']})(Dummy); /** * A simple component that renders the existing layout and checks wether the currentUser is an admin or not. From ac2349f2ff9e6b116898e4f7d5e945ed23041f00 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Thu, 10 Jan 2019 15:12:19 +0100 Subject: [PATCH 10/11] Update validation callbacks' debug page The API for validation callbacks changed some time ago and the debug page was not updated to reflect this. --- .../lib/modules/default_mutations.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/vulcan-core/lib/modules/default_mutations.js b/packages/vulcan-core/lib/modules/default_mutations.js index 1f0950993..50a43b840 100644 --- a/packages/vulcan-core/lib/modules/default_mutations.js +++ b/packages/vulcan-core/lib/modules/default_mutations.js @@ -207,11 +207,12 @@ const registerCollectionCallbacks = (typeName, options) => { if (options.create) { registerCallback({ name: `${typeName}.create.validate`, - iterator: { document: 'The document being inserted' }, + iterator: { validationErrors: 'An array that can be used to accumulate validation errors' }, properties: [ { document: 'The document being inserted' }, { currentUser: 'The current user' }, - { validationErrors: 'An object that can be used to accumulate validation errors' }, + { collection: 'The collection the document belongs to' }, + { context: 'The context of the mutation'}, ], runs: 'sync', returns: 'document', @@ -248,11 +249,13 @@ const registerCollectionCallbacks = (typeName, options) => { if (options.update) { registerCallback({ name: `${typeName}.update.validate`, - iterator: { data: 'The client data' }, + iterator: { validationErrors: 'An object that can be used to accumulate validation errors' }, properties: [ { document: 'The document being edited' }, + { data: 'The client data' }, { currentUser: 'The current user' }, - { validationErrors: 'An object that can be used to accumulate validation errors' }, + { collection: 'The collection the document belongs to' }, + { context: 'The context of the mutation'}, ], runs: 'sync', returns: 'modifier', @@ -296,10 +299,12 @@ const registerCollectionCallbacks = (typeName, options) => { if (options.delete) { registerCallback({ name: `${typeName}.delete.validate`, - iterator: { document: 'The document being removed' }, + iterator: { validationErrors: 'An object that can be used to accumulate validation errors' }, properties: [ { currentUser: 'The current user' }, - { validationErrors: 'An object that can be used to accumulate validation errors' }, + { document: 'The document being removed' }, + { collection: 'The collection the document belongs to'}, + { context: 'The context of this mutation'} ], runs: 'sync', returns: 'document', From d912e4a2241dc0c32d5352984903ff2f10f825d0 Mon Sep 17 00:00:00 2001 From: Apollinaire Date: Tue, 15 Jan 2019 17:34:51 +0100 Subject: [PATCH 11/11] Add failureComponent and failureComponentName to `withAccess` --- .../lib/modules/containers/withAccess.js | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/packages/vulcan-core/lib/modules/containers/withAccess.js b/packages/vulcan-core/lib/modules/containers/withAccess.js index a778e5f82..b48ba6b01 100644 --- a/packages/vulcan-core/lib/modules/containers/withAccess.js +++ b/packages/vulcan-core/lib/modules/containers/withAccess.js @@ -1,31 +1,63 @@ -import React, { PureComponent } from 'react'; -import { withCurrentUser } from 'meteor/vulcan:core'; -import { withRouter } from 'react-router'; +import React, {PureComponent} from 'react'; +import {Components} from 'meteor/vulcan:lib'; +import withCurrentUser from './withCurrentUser'; +import {withRouter} from 'react-router'; import Users from 'meteor/vulcan:users'; -export default function withAccess (options) { +/** + * withAccess - description + * + * @param {Object} options the options that define the hoc + * @param {string[]} options.groups the groups that have access to this component + * @param {string} options.redirect the link to redirect to in case the access is not granted (optional) + * @param {string} options.failureComponentName the name of a component to display if access is not granted (optional) + * @param {Component} options.failureComponent the component to display if access is not granted (optional) + * @return {PureComponent} a React component that will display only if the acces is granted + */ - const { groups, redirect } = options; +export default function withAccess(options) { + const { + groups = [], + redirect = null, + failureComponent = null, + failureComponentName = null, + } = options; // we return a function that takes a component and itself returns a component return WrappedComponent => { class AccessComponent extends PureComponent { - // if there are any groups defined check if user belongs, else just check if user exists canAccess = currentUser => { return groups ? Users.isMemberOf(currentUser, groups) : currentUser; - } + }; // redirect on constructor if user cannot access constructor(props) { super(props); - if(!this.canAccess(props.currentUser) && typeof redirect === 'string') { + if ( + !this.canAccess(props.currentUser) && + typeof redirect === 'string' + ) { props.router.push(redirect); } } + renderFailureComponent() { + if (failureComponentName) { + const FailureComponent = Components[failureComponentName]; + return ; + } else if (failureComponent) { + const FailureComponent = failureComponent; // necesary because jsx components must be uppercase + return ; + } else return null; + } + render() { - return this.canAccess(this.props.currentUser) ? : null; + return this.canAccess(this.props.currentUser) ? ( + + ) : ( + this.renderFailureComponent() + ); } }