diff --git a/.meteor/packages b/.meteor/packages
index e662b375696..7333e819a98 100644
--- a/.meteor/packages
+++ b/.meteor/packages
@@ -95,3 +95,4 @@ johanbrook:publication-collector
# Custom Packages
+gadicc:blaze-react-component
diff --git a/.meteor/versions b/.meteor/versions
index e44d08e179a..f02dbcefa7b 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -70,6 +70,7 @@ email@1.1.18
es5-shim@4.6.15
facebook@1.2.10
fastclick@1.0.13
+gadicc:blaze-react-component@1.4.0
geojson-utils@1.0.10
google@1.1.15
hot-code-push@1.0.4
diff --git a/client/modules/accounts/templates/dropdown/dropdown.js b/client/modules/accounts/templates/dropdown/dropdown.js
index 10c7f5a4856..7b74a61067c 100644
--- a/client/modules/accounts/templates/dropdown/dropdown.js
+++ b/client/modules/accounts/templates/dropdown/dropdown.js
@@ -61,8 +61,11 @@ Template.loginDropdown.events({
});
}
});
- } else if (this.route || this.name) {
+ } else if (this.name !== "account/profile") {
event.preventDefault();
+ /** TMP **/
+ Reaction.showActionView(this);
+ } else if (this.route || this.name) {
const route = this.name || this.route;
Reaction.Router.go(route);
}
diff --git a/client/modules/core/main.js b/client/modules/core/main.js
index 000cadfc9bc..49e309f8a9c 100644
--- a/client/modules/core/main.js
+++ b/client/modules/core/main.js
@@ -251,7 +251,7 @@ export default {
setActionView(viewData) {
if (viewData) {
- Session.set("admin/actionView", viewData);
+ Session.set("admin/actionView", [viewData]);
} else {
const registryItem = this.getRegistryForCurrentRoute(
"settings");
@@ -266,8 +266,87 @@ export default {
}
},
+ pushActionView(viewData) {
+ Session.set("admin/showActionView", true);
+
+ const actionViewStack = Session.get("admin/actionView");
+
+ if (viewData) {
+ actionViewStack.push(viewData);
+ Session.set("admin/actionView", actionViewStack);
+ } else {
+ const registryItem = this.getRegistryForCurrentRoute(
+ "settings");
+
+ if (registryItem) {
+ this.pushActionView(registryItem);
+ } else {
+ this.pushActionView({ template: "blankControls" });
+ }
+ }
+ },
+
+ isActionViewAtRootView() {
+ const actionViewStack = Session.get("admin/actionView");
+
+ if (Array.isArray(actionViewStack) && actionViewStack.length === 1) {
+ return true;
+ }
+
+ return false;
+ },
+
+ popActionView() {
+ const actionViewStack = Session.get("admin/actionView");
+ actionViewStack.pop();
+
+ Session.set("admin/actionView", actionViewStack);
+
+ this.setActionViewDetail({});
+ },
+
+ setActionViewDetail(viewData) {
+ if (viewData) {
+ Session.set("admin/detailView", [viewData]);
+ }
+ },
+
+ pushActionViewDetail(viewData) {
+ Session.set("admin/showActionView", true);
+
+ const detailViewStack = Session.get("admin/detailView");
+
+ if (viewData) {
+ detailViewStack.push(viewData);
+ Session.set("admin/detailView", detailViewStack);
+ }
+ },
+
+ popActionViewDetail() {
+ const detailViewStack = Session.get("admin/detailView");
+ detailViewStack.pop();
+
+ Session.set("admin/detailView", detailViewStack);
+ },
+
getActionView() {
- return Session.get("admin/actionView") || {};
+ const actionViewStack = Session.get("admin/actionView");
+
+ if (Array.isArray(actionViewStack) && actionViewStack.length) {
+ return actionViewStack.pop();
+ }
+
+ return {};
+ },
+
+ getActionViewDetail() {
+ const detailViewStack = Session.get("admin/detailView");
+
+ if (Array.isArray(detailViewStack) && detailViewStack.length) {
+ return detailViewStack.pop();
+ }
+
+ return {};
},
hideActionView() {
@@ -275,10 +354,14 @@ export default {
},
clearActionView() {
- Session.set("admin/actionView", {
+ Session.set("admin/actionView", [{
label: "",
i18nKeyLabel: ""
- });
+ }]);
+ Session.set("admin/detailView", [{
+ label: "",
+ i18nKeyLabel: ""
+ }]);
},
getCurrentTag() {
@@ -295,7 +378,8 @@ export default {
// find registry entries for routeName
const reactionApp = Packages.findOne({
"registry.name": currentRouteName,
- "registry.provides": provides
+ "registry.provides": provides,
+ "enabled": true
}, {
enabled: 1,
registry: 1,
diff --git a/imports/plugins/core/dashboard/client/components/actionView.js b/imports/plugins/core/dashboard/client/components/actionView.js
new file mode 100644
index 00000000000..2d2d797378b
--- /dev/null
+++ b/imports/plugins/core/dashboard/client/components/actionView.js
@@ -0,0 +1,227 @@
+import React, { Component, PropTypes } from "react";
+import classnames from "classnames";
+import Blaze from "meteor/gadicc:blaze-react-component";
+import {
+ IconButton,
+ Translation
+} from "/imports/plugins/core/ui/client/components";
+import { Admin } from "/imports/plugins/core/ui/client/providers";
+import Radium from "radium";
+import Velocity from "velocity-animate";
+import "velocity-animate/velocity.ui";
+import { VelocityTransitionGroup } from "velocity-react";
+
+const getStyles = (props) => {
+ let viewSize = 400;
+ // if (props.actionView && props.actionView.priority === 1 && props.actionView.provides === "dashboard") {
+ if (props.actionView && props.actionView.provides === "dashboard") {
+ viewSize = "90vw";
+ }
+
+ return {
+ base: {
+ display: "flex",
+ flexDirection: "column",
+ height: "100vh",
+ position: "relative",
+ width: viewSize
+ },
+ header: {
+ display: "flex",
+ alignItems: "center",
+ position: "relative",
+ height: "56px",
+ padding: "0 20px",
+ margin: 0
+ },
+ heading: {
+ display: "flex",
+ alignItems: "center",
+ flex: "1 1 auto",
+ position: "relative",
+ margin: 0,
+ height: "100%"
+ },
+ body: {
+ display: "flex",
+ webkitOverflowScrolling: "touch"
+ },
+ masterView: {
+ flex: "1 1 auto",
+ height: "100%",
+ overflow: "auto",
+ webkitOverflowScrolling: "touch"
+ },
+ detailView: {
+ width: "400px",
+ height: "100%",
+ overflow: "auto",
+ webkitOverflowScrolling: "touch"
+ },
+ title: {
+ margin: 0,
+ transition: "200ms all"
+ },
+ titleWithBackButton: {
+ paddingLeft: 40
+ },
+ backButton: {
+ height: "100%",
+ position: "absolute",
+ top: 0,
+ zIndex: 1
+ },
+ backButtonContainers: {
+ display: "flex",
+ alignItems: "center",
+ height: "100%"
+ }
+ };
+};
+
+class ActionView extends Component {
+ static propTypes = {
+ actionView: PropTypes.object,
+ actionViewIsOpen: PropTypes.bool,
+ buttons: PropTypes.array,
+ isActionViewAtRootView: PropTypes.bool
+ }
+
+ renderControlComponent() {
+ if (this.props.actionView && typeof this.props.actionView.template === "string") {
+ return (
+
+
+
+ );
+ }
+
+ return null;
+ }
+
+ renderDetailComponent() {
+ if (this.props.detailView && typeof this.props.detailView.template === "string") {
+ return (
+
+
+
+ );
+ }
+
+ return null;
+ }
+
+ renderFooter() {
+ // if (this.props.footerTemplate) {
+ // return (
+ //
+ // );
+ // }
+ }
+
+ renderBackButton() {
+ if (this.props.isActionViewAtRootView === false) {
+ return (
+
+ );
+ }
+ }
+
+ get styles() {
+ return getStyles(this.props);
+ }
+
+ get backButtonEnterAnimation() {
+ return {
+ animation: {
+ display: "flex",
+ position: "absolute",
+ left: 20,
+ opaticy: 1
+ },
+ duration: 200
+ };
+ }
+
+ get backButtonLeaveAnimaton() {
+ return {
+ animation: {
+ display: "flex",
+ position: "absolute",
+ left: -30,
+ opaticy: 0
+ },
+ duration: 200
+
+ };
+ }
+
+ render() {
+ const { actionView } = this.props;
+ const baseClassName = classnames({
+ "admin-controls": true,
+ "show-settings": this.props.actionViewIsOpen
+ });
+
+
+ return (
+
+
+
+ {this.renderBackButton()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.renderControlComponent()}
+ {this.renderDetailComponent()}
+
+
+
+ {this.renderFooter()}
+
+
+
+
+ );
+ }
+}
+
+export default Admin()(Radium(ActionView));
diff --git a/imports/plugins/core/dashboard/client/components/index.js b/imports/plugins/core/dashboard/client/components/index.js
new file mode 100644
index 00000000000..35a4a4d6ebb
--- /dev/null
+++ b/imports/plugins/core/dashboard/client/components/index.js
@@ -0,0 +1,2 @@
+export { default as ActionView } from "./actionView";
+export { default as PackageList } from "./packageList";
diff --git a/imports/plugins/core/dashboard/client/components/packageList.js b/imports/plugins/core/dashboard/client/components/packageList.js
new file mode 100644
index 00000000000..01a86199f98
--- /dev/null
+++ b/imports/plugins/core/dashboard/client/components/packageList.js
@@ -0,0 +1,62 @@
+import React, { Component, PropTypes } from "react";
+import { Card, CardHeader, CardBody, List, ListItem } from "/imports/plugins/core/ui/client/components"
+import { map } from "lodash"
+class PackageList extends Component {
+
+ // renderPackages() {
+ // if (Array.isArray(this.props.packages)) {
+ // return this.props.packages.map((packageData) => {
+ // return (
+ //
+ // );
+ // });
+ // }
+ // }
+
+ renderPackages() {
+ if (true) {
+ return map(this.props.groupedPackages, (group, name) => {
+
+ const items = group.map((packageData) => {
+ return (
+
+ );
+ })
+
+
+ return (
+
+
+
+ {items}
+
+
+ )
+
+ });
+ }
+ }
+ render() {
+ return (
+
+ {this.renderPackages()}
+
+ );
+ }
+}
+
+export default PackageList;
diff --git a/imports/plugins/core/dashboard/client/containers/actionViewContainer.js b/imports/plugins/core/dashboard/client/containers/actionViewContainer.js
new file mode 100644
index 00000000000..14513db31a7
--- /dev/null
+++ b/imports/plugins/core/dashboard/client/containers/actionViewContainer.js
@@ -0,0 +1,91 @@
+import React, { Component, PropTypes } from "react";
+import { composeWithTracker } from "/lib/api/compose";
+import { Admin } from "../components"
+
+import { Meteor } from "meteor/meteor";
+import { Blaze } from "meteor/blaze";
+import { Template } from "meteor/templating";
+import { Reaction, i18next } from "/client/api";
+import { Packages } from "/lib/collections";
+
+import { TranslationProvider, AdminContextProvider } from "/imports/plugins/core/ui/client/providers";
+import { Loading } from "/imports/plugins/core/ui/client/components";
+
+
+function handleActionViewBack() {
+ Reaction.popActionView();
+}
+
+function handleActionViewClose() {
+ Reaction.hideActionView();
+}
+
+function composer(props, onData) {
+ const shortcuts = Reaction.Apps({ provides: "shortcut", enabled: true });
+ const items = [];
+
+ if (_.isArray(shortcuts)) {
+ for (const shortcut of shortcuts) {
+ if (!shortcut.container) {
+ items.push({
+ type: "link",
+ href: Reaction.Router.pathFor(shortcut.name),
+ className: Reaction.Router.isActiveClassName(shortcut.name),
+ icon: shortcut.icon,
+ tooltip: shortcut.label || "",
+ i18nKeyTooltip: shortcut.i18nKeyLabel,
+ tooltipPosition: "left middle"
+ });
+ }
+ }
+ }
+
+ items.push({ type: "seperator" });
+
+ items.push({
+ icon: "plus",
+ tooltip: "Create Content",
+ i18nKeyTooltip: "app.createContent",
+ tooltipPosition: "left middle",
+ // onClick(event) {
+ // if (!instance.dropInstance) {
+ // instance.dropInstance = new Drop({ target: event.currentTarget, content: "", constrainToWindow: true, classes: "drop-theme-arrows", position: "right center" });
+ //
+ // Blaze.renderWithData(Template.createContentMenu, {}, instance.dropInstance.content);
+ // }
+ //
+ // instance.dropInstance.open();
+ // }
+ });
+
+
+
+
+ onData(null, {
+ isAdminArea: true,
+ actionView: Reaction.getActionView(),
+ detailView: Reaction.getActionViewDetail(),
+ data: props.data,
+ buttons: items,
+ isActionViewAtRootView: Reaction.isActionViewAtRootView(),
+ actionViewIsOpen: Reaction.isActionViewOpen(),
+
+ // Callbacks
+ handleActionViewBack,
+ handleActionViewClose
+ });
+}
+
+export default function ActionViewContainer(Comp) {
+ function CompositeComponent(props) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ return composeWithTracker(composer, Loading)(CompositeComponent);
+}
diff --git a/imports/plugins/core/dashboard/client/containers/index.js b/imports/plugins/core/dashboard/client/containers/index.js
new file mode 100644
index 00000000000..cee580eb26b
--- /dev/null
+++ b/imports/plugins/core/dashboard/client/containers/index.js
@@ -0,0 +1,2 @@
+export { default as PackageListContainer } from "./packageListContainer";
+export { default as ActionViewContainer } from "./actionViewContainer";
diff --git a/imports/plugins/core/dashboard/client/containers/packageListContainer.js b/imports/plugins/core/dashboard/client/containers/packageListContainer.js
new file mode 100644
index 00000000000..dd92f405ba7
--- /dev/null
+++ b/imports/plugins/core/dashboard/client/containers/packageListContainer.js
@@ -0,0 +1,68 @@
+import React from "react";
+import { groupBy } from "lodash";
+import { composeWithTracker } from "/lib/api/compose";
+import { Reaction } from "/client/api";
+import { Loading } from "/imports/plugins/core/ui/client/components";
+import { TranslationProvider } from "/imports/plugins/core/ui/client/providers";
+
+/**
+ * handleShowPackage - Push package into action view navigation stack
+ * @param {SyntheticEvent} event Original event
+ * @param {Object} app Package data
+ * @return {undefined} No return value
+ */
+function handleShowPackage(event, app) {
+ Reaction.pushActionView(app);
+}
+
+function composer(props, onData) {
+ const settings = Reaction.Apps({ provides: "settings", enabled: true }) || [];
+
+ const dashboard = Reaction.Apps({ provides: "dashboard", enabled: true }).filter((d) => typeof d.template !== "undefined") || [];
+
+
+
+ // const packages = apps.map((packageData) => {
+ // const appData = Reaction.Apps({
+ // provides: "settings",
+ // name: packageData.packageName
+ // });
+ //
+ // if ((!packageData.route || !packageData.template) && appData.length) {
+ // return {
+ // ...packageData,
+ // ...appData[0]
+ // };
+ // }
+ //
+ // return packageData;
+ // });
+
+ // const groupedPackages = groupBy(packages, (app) => {
+ // return app.container || "misc";
+ // });
+
+ onData(null, {
+ // packages,
+ groupedPackages: {
+ dashboard: dashboard,
+ settings: settings
+ },
+ // groups: Object.keys(groupedPackages),
+
+ // Callbacks
+ handleShowPackage
+ });
+}
+
+export default function PackageListContainer(Comp) {
+ function CompositeComponent(props) {
+ return (
+
+
+
+ );
+ }
+
+ return composeWithTracker(composer, Loading)(CompositeComponent);
+}
diff --git a/imports/plugins/core/dashboard/client/index.js b/imports/plugins/core/dashboard/client/index.js
index b93b61b28ff..62272977648 100644
--- a/imports/plugins/core/dashboard/client/index.js
+++ b/imports/plugins/core/dashboard/client/index.js
@@ -6,6 +6,7 @@ import "./templates/packages/grid/grid.js";
import "./templates/packages/grid/package.html";
import "./templates/packages/grid/package.js";
import "./templates/packages/packages.html";
+import "./templates/packages/packages.js";
import "./templates/settings/settings.html";
import "./templates/settings/settings.js";
diff --git a/imports/plugins/core/dashboard/client/templates/packages/grid/package.js b/imports/plugins/core/dashboard/client/templates/packages/grid/package.js
index 159454a7f7c..bdae24a8374 100644
--- a/imports/plugins/core/dashboard/client/templates/packages/grid/package.js
+++ b/imports/plugins/core/dashboard/client/templates/packages/grid/package.js
@@ -1,5 +1,4 @@
import { Reaction } from "/client/api";
-
/* eslint no-loop-func: 0 */
/**
@@ -59,7 +58,7 @@ Template.gridPackage.helpers({
controls.push({
icon: app.icon || "fa fa-cog fa-fw",
onClick() {
- Reaction.showActionView(app);
+ Reaction.pushActionView(app);
}
});
}
@@ -68,7 +67,7 @@ Template.gridPackage.helpers({
controls.push({
icon: "angle-right",
onClick() {
- showPackageDashboard(data.package);
+ Reaction.pushActionView(data.package);
}
});
}
@@ -76,7 +75,7 @@ Template.gridPackage.helpers({
return {
controls,
onContentClick() {
- showPackageDashboard(data.package);
+ Reaction.pushActionView(data.package);
}
};
},
diff --git a/imports/plugins/core/dashboard/client/templates/packages/packages.html b/imports/plugins/core/dashboard/client/templates/packages/packages.html
index 86b4875dea7..d4affa92562 100644
--- a/imports/plugins/core/dashboard/client/templates/packages/packages.html
+++ b/imports/plugins/core/dashboard/client/templates/packages/packages.html
@@ -1,5 +1,5 @@
-
- {{> packagesGrid}}
+
+ {{> React PackageListComponent}}
diff --git a/imports/plugins/core/dashboard/client/templates/packages/packages.js b/imports/plugins/core/dashboard/client/templates/packages/packages.js
new file mode 100644
index 00000000000..15fc8a9e184
--- /dev/null
+++ b/imports/plugins/core/dashboard/client/templates/packages/packages.js
@@ -0,0 +1,10 @@
+import { PackageList } from "../../components";
+import { PackageListContainer } from "../../containers";
+
+Template.dashboardPackages.helpers({
+ PackageListComponent() {
+ return {
+ component: PackageListContainer(PackageList)
+ };
+ }
+});
diff --git a/imports/plugins/core/dashboard/client/templates/settings/settings.html b/imports/plugins/core/dashboard/client/templates/settings/settings.html
index 3d9e8020949..f94e393f60e 100644
--- a/imports/plugins/core/dashboard/client/templates/settings/settings.html
+++ b/imports/plugins/core/dashboard/client/templates/settings/settings.html
@@ -10,6 +10,11 @@
+ {{#unless isActionViewAtRootView}}
+
+ {{/unless}}
{{#with registry}}
diff --git a/imports/plugins/core/dashboard/client/templates/settings/settings.js b/imports/plugins/core/dashboard/client/templates/settings/settings.js
index 98a9cb515ec..8e57e560695 100644
--- a/imports/plugins/core/dashboard/client/templates/settings/settings.js
+++ b/imports/plugins/core/dashboard/client/templates/settings/settings.js
@@ -15,6 +15,10 @@ Template.settingsHeader.helpers({
return Reaction.getActionView() || {};
},
+ isActionViewAtRootView() {
+ return Reaction.isActionViewAtRootView();
+ },
+
/**
* thisApp
* @return {Object} Registry entry for item
@@ -48,6 +52,10 @@ Template.settingsHeader.helpers({
Template.settingsHeader.events({
"click [data-event-action=closeSettings]": () => {
Reaction.hideActionView();
+ },
+
+ "click .js-back-button"() {
+ Reaction.popActionView();
}
});
diff --git a/imports/plugins/core/layout/client/templates/layout/admin/admin.html b/imports/plugins/core/layout/client/templates/layout/admin/admin.html
index 03aa57162f2..a7dfed557ec 100644
--- a/imports/plugins/core/layout/client/templates/layout/admin/admin.html
+++ b/imports/plugins/core/layout/client/templates/layout/admin/admin.html
@@ -1,6 +1,11 @@
{{> inlineAlerts}}
+
+
+ {{> React PublishContainerComponent }}
+
+
-
- {{> Template.dynamic template=dashboardHeader}}
-
-
{{> Template.dynamic template=template}}
@@ -28,51 +29,7 @@
-
-
-
- {{> settingsHeader}}
-
-
-
- {{> Template.dynamic template=control.template data=control.data}}
-
-
-
-
-
-
-