diff --git a/imports/plugins/core/ui-navbar/client/components/brand.js b/imports/plugins/core/ui-navbar/client/components/brand.js
deleted file mode 100644
index 038f52ddfd..0000000000
--- a/imports/plugins/core/ui-navbar/client/components/brand.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-import { registerComponent } from "@reactioncommerce/reaction-components";
-import { Reaction } from "/client/api";
-
-class Brand extends Component {
- static propTypes = {
- logo: PropTypes.string,
- title: PropTypes.string
- }
-
- handleClick = (event) => {
- event.preventDefault();
- Reaction.Router.go("/");
- }
-
- render() {
- const { logo, title } = this.props;
-
- return (
-
- {this.props.logo &&
-
-
-
- }
- {title}
-
- );
- }
-}
-
-registerComponent("Brand", Brand);
-
-export default Brand;
diff --git a/imports/plugins/core/ui-navbar/client/components/navbar.js b/imports/plugins/core/ui-navbar/client/components/navbar.js
deleted file mode 100644
index 54640921a7..0000000000
--- a/imports/plugins/core/ui-navbar/client/components/navbar.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-import { Components } from "@reactioncommerce/reaction-components";
-
-class NavBar extends Component {
- static propTypes = {
- brandMedia: PropTypes.object,
- hasProperPermission: PropTypes.bool,
- searchEnabled: PropTypes.bool, // eslint-disable-line react/boolean-prop-naming
- shop: PropTypes.object.isRequired,
- visibility: PropTypes.object.isRequired
- };
-
- static defaultProps = {
- visibility: {
- hamburger: true,
- brand: true,
- tags: true,
- search: true,
- notifications: true,
- languages: true,
- currency: true,
- mainDropdown: true
- }
- };
-
- state = {
- navBarVisible: false,
- searchModalOpen: false
- }
-
- toggleNavbarVisibility = () => {
- const isVisible = this.state.navBarVisible;
- this.setState({ navBarVisible: !isVisible });
- }
-
- handleCloseNavbar = () => {
- this.setState({ navBarVisible: false });
- }
-
- handleOpenSearchModal = () => {
- this.setState({ searchModalOpen: true });
- }
-
- handleCloseSearchModal = () => {
- this.setState({ searchModalOpen: false });
- }
-
- renderBrand() {
- const { brandMedia, shop } = this.props;
-
- const { name } = shop || {};
- const logo = brandMedia && brandMedia.url({ store: "large" });
-
- return (
-
- );
- }
-
- renderSearchButton() {
- if (this.props.searchEnabled) {
- return (
-
-
-
-
- );
- }
-
- return null;
- }
-
- renderNotificationIcon() {
- if (this.props.hasProperPermission) {
- return (
-
-
-
- );
- }
-
- return null;
- }
-
- renderMainDropdown() {
- return (
-
- );
- }
-
- renderHamburgerButton() {
- return (
-
- );
- }
-
- renderTagNav() {
- return (
-
-
- {this.renderNotificationIcon()}
-
- );
- }
-
- render() {
- return (
-
- {this.props.visibility.hamburger && this.renderHamburgerButton()}
- {this.props.visibility.brand && this.renderBrand()}
-
- {this.props.visibility.tags && this.renderTagNav()}
-
- {this.props.visibility.search && this.renderSearchButton()}
- {this.props.visibility.notifications && this.renderNotificationIcon()}
- {this.props.visibility.currency && this.renderCurrency()}
- {this.props.visibility.mainDropdown && this.renderMainDropdown()}
-
- );
- }
-}
-
-export default NavBar;
diff --git a/imports/plugins/core/ui-navbar/client/components/navbarCheckout.js b/imports/plugins/core/ui-navbar/client/components/navbarCheckout.js
deleted file mode 100644
index 490860acce..0000000000
--- a/imports/plugins/core/ui-navbar/client/components/navbarCheckout.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from "react";
-import NavBar from "../components/navbar";
-
-const NavBarCheckout = (props, context) => {
- const visibility = {
- hamburger: false,
- brand: true,
- tags: false,
- search: false,
- notifications: false,
- languages: false,
- currency: false,
- mainDropdown: false
- };
- const newProps = {
- ...props,
- visibility
- };
- return React.createElement(NavBar, newProps, context);
-};
-
-export default NavBarCheckout;
diff --git a/imports/plugins/core/ui-navbar/client/containers/navbar.js b/imports/plugins/core/ui-navbar/client/containers/navbar.js
deleted file mode 100644
index cc0b8ff9d3..0000000000
--- a/imports/plugins/core/ui-navbar/client/containers/navbar.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import { registerComponent, composeWithTracker } from "@reactioncommerce/reaction-components";
-import { Meteor } from "meteor/meteor";
-import { Roles } from "meteor/alanning:roles";
-import { Reaction } from "/client/api";
-import NavBar from "../components/navbar";
-import { Shops } from "/lib/collections";
-import { Media } from "/imports/plugins/core/files/client";
-
-/**
- * @private
- * @param {Object} props Props
- * @param {Function} onData Call this to update props
- * @returns {undefined}
- */
-export function composer(props, onData) {
- const shop = Shops.findOne({ _id: Reaction.getShopId() });
- if (!shop) throw new Error(`No shop found with shop ID ${Reaction.getShopId()}`);
-
- const searchPackage = Reaction.Apps({ provides: "ui-search" });
- const user = Meteor.user();
- let searchEnabled;
- let searchTemplate;
- let brandMedia;
-
- let shops;
-
- if (user && user.roles) {
- // Get all shops for which user has roles
- shops = Shops.find({
- $and: [
- { _id: { $in: Object.keys(user.roles) } },
- { $or: [{ "workflow.status": "active" }, { _id: Reaction.getPrimaryShopId() }] }
- ]
- }).fetch();
- }
-
- /**
- * @method
- * @summary Handle change in selected shop
- * @param {script} event DOM Event
- * @param {String} shopId - selected shopId
- * @since 1.5.8
- * @returns {void}
- * @private
- */
- const handleShopSelectChange = (event, shopId) => {
- Reaction.setShopId(shopId);
- };
-
- const isLoggedIn = !!(shop && user && !Roles.userIsInRole(user._id, "anonymous", shop._id));
-
- if (searchPackage.length && isLoggedIn) {
- searchEnabled = true;
- searchTemplate = searchPackage[0].template;
- } else {
- searchEnabled = false;
- }
-
- if (shop && Array.isArray(shop.brandAssets)) {
- const brandAsset = shop.brandAssets.find((asset) => asset.type === "navbarBrandImage");
- brandMedia = brandAsset && Media.findOneLocal(brandAsset.mediaId);
- }
-
- const hasProperPermission = Reaction.hasPermission("account/profile");
-
- onData(null, {
- brandMedia,
- handleShopSelectChange,
- hasProperPermission,
- searchEnabled,
- searchTemplate,
- shop,
- shops,
- visibility: {
- hamburger: true,
- brand: true,
- tags: isLoggedIn,
- search: true,
- notifications: true,
- languages: true,
- currency: true,
- mainDropdown: true
- }
- });
-}
-
-registerComponent("NavBar", NavBar, composeWithTracker(composer));
-
-export default composeWithTracker(composer)(NavBar);
diff --git a/imports/plugins/core/ui-navbar/client/containers/navbarCheckout.js b/imports/plugins/core/ui-navbar/client/containers/navbarCheckout.js
deleted file mode 100644
index 7a59f0475d..0000000000
--- a/imports/plugins/core/ui-navbar/client/containers/navbarCheckout.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { registerComponent, composeWithTracker } from "@reactioncommerce/reaction-components";
-import NavBarCheckout from "../components/navbarCheckout";
-import { composer } from "./navbar";
-
-registerComponent("NavBarCheckout", NavBarCheckout, composeWithTracker(composer));
-
-export default composeWithTracker(composer)(NavBarCheckout);
diff --git a/imports/plugins/core/ui-navbar/client/index.js b/imports/plugins/core/ui-navbar/client/index.js
deleted file mode 100644
index 639529c622..0000000000
--- a/imports/plugins/core/ui-navbar/client/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export { default as Brand } from "./components/brand";
-export { default as Navbar } from "./containers/navbar";
-export { default as NavBarCheckout } from "./containers/navbarCheckout";
diff --git a/imports/plugins/core/ui-tagnav/client/components/tagGroup.js b/imports/plugins/core/ui-tagnav/client/components/tagGroup.js
deleted file mode 100644
index ae6862ae8d..0000000000
--- a/imports/plugins/core/ui-tagnav/client/components/tagGroup.js
+++ /dev/null
@@ -1,175 +0,0 @@
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-import _ from "lodash";
-import { Components, registerComponent } from "@reactioncommerce/reaction-components";
-import update from "immutability-helper";
-import { TagHelpers } from "/imports/plugins/core/ui-tagnav/client/helpers";
-import getTagSuggestions from "/imports/plugins/core/ui-tagnav/client/util/getTagSuggestions";
-import { getTagIds } from "/lib/selectors/tags";
-import { Router } from "/client/api";
-
-class TagGroup extends Component {
- constructor(props) {
- super(props);
-
- const { parentTag, tagsByKey, tagIds } = props.tagGroupProps;
- this.state = {
- suggestions: [],
- newTag: {
- name: ""
- },
- tagIds,
- parentTag,
- tagsByKey
- };
- }
-
- // eslint-disable-next-line camelcase
- UNSAFE_componentWillReceiveProps(nextProps) {
- const { parentTag, tagsByKey, tagIds } = nextProps.tagGroupProps;
- this.setState({ tagIds, parentTag, tagsByKey });
- }
-
- get tags() {
- if (this.props.editable) {
- return this.state.tagIds.map((tagId) => this.state.tagsByKey[tagId]);
- }
-
- return this.props.tagGroupProps.subTagGroups;
- }
-
- get className() {
- if (this.props.blank) {
- return "create";
- }
- return "";
- }
-
- handleGetSuggestions = async (suggestionUpdateRequest) => {
- const suggestions = await getTagSuggestions(
- suggestionUpdateRequest.value,
- { excludeTags: this.state.tagIds }
- );
-
- this.setState({ suggestions });
- }
-
- handleClearSuggestions = () => {
- this.setState({ suggestions: [] });
- }
-
- handleNewTagSave = (event, tag) => {
- if (this.props.onNewTagSave) {
- this.props.onNewTagSave(tag, this.props.tagGroupProps.parentTag);
- this.setState({
- newTag: { name: "" }
- });
- }
- }
-
- handleTagUpdate = (event, tag) => {
- const newState = update(this.state, {
- tagsByKey: {
- [tag._id]: {
- $set: tag
- }
- }
- });
-
- this.setState(newState);
- }
-
- handleNewTagUpdate = (event, tag) => { // updates blank tag state being edited
- this.setState({ newTag: tag });
- }
-
- tagGroupBodyProps = (tag) => {
- const subTagGroups = _.compact(TagHelpers.subTags(tag));
- const tagsByKey = {};
-
- if (Array.isArray(subTagGroups)) {
- for (const tagItem of subTagGroups) {
- tagsByKey[tagItem._id] = tagItem;
- }
- }
-
- return {
- parentTag: tag,
- tagsByKey: tagsByKey || {},
- tagIds: getTagIds({ tags: subTagGroups }) || [],
- subTagGroups
- };
- }
-
- renderTree(tags) {
- if (Array.isArray(tags)) {
- return tags.map((tag) => (
-
-
-
-
- ));
- }
-
- return null;
- }
-
- render() {
- const { slug } = this.state.parentTag;
- const url = Router.pathFor("tag", {
- hash: {
- slug
- }
- });
- return (
-
-
-
{this.state.parentTag.name}
-
View All
-
-
- {this.renderTree(this.tags)}
- {this.props.editable &&
-
- }
-
-
- );
- }
-}
-
-TagGroup.propTypes = {
- blank: PropTypes.bool, // eslint-disable-line react/boolean-prop-naming
- editable: PropTypes.bool, // eslint-disable-line react/boolean-prop-naming
- onNewTagSave: PropTypes.func,
- onTagRemove: PropTypes.func,
- tagGroupProps: PropTypes.object
-};
-
-registerComponent("TagGroup", TagGroup);
-
-export default TagGroup;
diff --git a/imports/plugins/core/ui-tagnav/client/components/tagGroupBody.js b/imports/plugins/core/ui-tagnav/client/components/tagGroupBody.js
deleted file mode 100644
index 34ac341227..0000000000
--- a/imports/plugins/core/ui-tagnav/client/components/tagGroupBody.js
+++ /dev/null
@@ -1,177 +0,0 @@
-import _ from "lodash";
-import React, { Component } from "react";
-import update from "immutability-helper";
-import PropTypes from "prop-types";
-import { Components, registerComponent } from "@reactioncommerce/reaction-components";
-import getTagSuggestions from "/imports/plugins/core/ui-tagnav/client/util/getTagSuggestions";
-
-class TagGroupBody extends Component {
- constructor(props) {
- super(props);
-
- const { parentTag, tagsByKey, tagIds } = props.tagGroupBodyProps;
- this.state = {
- suggestions: [],
- newTag: {
- name: ""
- },
- tagIds,
- parentTag,
- tagsByKey
- };
- }
-
- // eslint-disable-next-line camelcase
- UNSAFE_componentWillReceiveProps(nextProps) {
- const { parentTag, tagsByKey, tagIds } = nextProps.tagGroupBodyProps;
- this.setState({ tagIds, parentTag, tagsByKey });
- }
-
- handleNewTagSave = (event, tag) => {
- if (this.props.onNewTagSave) {
- this.props.onNewTagSave(tag, this.state.parentTag);
- this.setState({
- newTag: { name: "" }
- });
- }
- }
-
- handleTagUpdate = (event, tag) => {
- const newState = update(this.state, {
- tagsByKey: {
- [tag._id]: {
- $set: tag
- }
- }
- });
-
- this.setState(newState);
- }
-
- handleNewTagUpdate = (event, tag) => { // updates blank tag state being edited
- this.setState({ newTag: tag });
- }
-
- handleGetSuggestions = async (suggestionUpdateRequest) => {
- const suggestions = await getTagSuggestions(
- suggestionUpdateRequest.value,
- { excludeTags: this.state.tagIds }
- );
-
- this.setState({ suggestions });
- }
-
- handleClearSuggestions = () => {
- this.setState({ suggestions: [] });
- }
-
- handleMoveTag = (dragIndex, hoverIndex) => {
- const tag = this.state.tagIds[dragIndex];
- if (!tag) {
- return false;
- }
- // Apply new sort order to variant list
- const newState = update(this.state, {
- tagIds: {
- $splice: [
- [dragIndex, 1],
- [hoverIndex, 0, tag]
- ]
- }
- });
-
- // Set local state so the component does't have to wait for a round-trip
- // to the server to get the updated list of variants
- return this.setState(newState, () => {
- _.debounce(() => this.props.onTagSort(this.state.tagIds, this.state.parentTag), 500)();
- });
- }
-
- handleTagSave = (event, tag) => {
- if (this.props.onUpdateTag) {
- this.props.onUpdateTag(tag._id, tag.name, this.state.parentTag._id);
- }
- }
-
- get tags() {
- if (this.props.editable) {
- return this.state.tagIds.map((tagId) => this.state.tagsByKey[tagId]);
- }
-
- return this.props.tagGroupBodyProps.subTagGroups;
- }
-
- genTagsList(tags, parentTag) {
- if (Array.isArray(tags)) {
- return tags.map((tag, index) => (
-
- ));
- }
-
- return null;
- }
-
- render() {
- return (
-
-
- {this.genTagsList(_.compact(this.tags), this.state.parentTag)}
- {this.props.editable &&
-
-
-
- }
-
-
- );
- }
-}
-
-TagGroupBody.propTypes = {
- editable: PropTypes.bool, // eslint-disable-line react/boolean-prop-naming
- onNewTagSave: PropTypes.func,
- onTagClick: PropTypes.func,
- onTagRemove: PropTypes.func,
- onTagSort: PropTypes.func,
- onUpdateTag: PropTypes.func,
- tagGroupBodyProps: PropTypes.object
-};
-
-registerComponent("TagGroupBody", TagGroupBody);
-
-export default TagGroupBody;
diff --git a/imports/plugins/core/ui-tagnav/client/components/tagGroupHeader.js b/imports/plugins/core/ui-tagnav/client/components/tagGroupHeader.js
deleted file mode 100644
index 8dc8f6777c..0000000000
--- a/imports/plugins/core/ui-tagnav/client/components/tagGroupHeader.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-import { Components, registerComponent } from "@reactioncommerce/reaction-components";
-import getTagSuggestions from "/imports/plugins/core/ui-tagnav/client/util/getTagSuggestions";
-
-class TagGroupHeader extends Component {
- constructor(props) {
- super(props);
- this.state = {
- suggestions: [],
- tag: this.props.tag
- };
- }
-
- handleGetSuggestions = async (suggestionUpdateRequest) => {
- const suggestions = await getTagSuggestions(
- suggestionUpdateRequest.value,
- { excludeTags: this.state.tagIds }
- );
-
- this.setState({ suggestions });
- }
-
- handleTagUpdate = (event, tag) => {
- this.setState({ tag });
- }
-
- handleTagSave = (event, tag) => {
- if (this.props.onUpdateTag) {
- this.props.onUpdateTag(tag._id, tag.name, this.props.parentTag._id);
- }
- }
-
- handleTagTreeMove = () => {
- // needed to prevent move errors, pending fix for TagGroup draging
- }
-
- render() {
- return (
-
-
-
- );
- }
-}
-
-TagGroupHeader.propTypes = {
- editable: PropTypes.bool, // eslint-disable-line react/boolean-prop-naming
- onTagClick: PropTypes.func,
- onTagRemove: PropTypes.func,
- onUpdateTag: PropTypes.func,
- parentTag: PropTypes.object,
- tag: PropTypes.object
-};
-
-registerComponent("TagGroupHeader", TagGroupHeader);
-
-export default TagGroupHeader;
diff --git a/imports/plugins/core/ui-tagnav/client/components/tagNav.js b/imports/plugins/core/ui-tagnav/client/components/tagNav.js
deleted file mode 100644
index 7e15d26b67..0000000000
--- a/imports/plugins/core/ui-tagnav/client/components/tagNav.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-import _ from "lodash";
-import { Components } from "@reactioncommerce/reaction-components";
-import { getTagIds } from "/lib/selectors/tags";
-import { TagHelpers } from "/imports/plugins/core/ui-tagnav/client/helpers";
-import ShopSelect from "/imports/plugins/core/dashboard/client/components/shopSelect";
-
-class TagNav extends Component {
- constructor(props) {
- super(props);
- this.state = {
- selectedTag: this.props.selectedTag || {}
- };
- }
-
- // eslint-disable-next-line camelcase
- UNSAFE_componentWillReceiveProps(nextProps) {
- this.setState({ selectedTag: nextProps.selectedTag });
- }
-
- /**
- * onShopSelectChange
- * @method
- * @summary Handle change in selected shop
- * @param {Script} event onchange event
- * @param {String} shopId - selected shopId
- * @since 1.5.8
- * @returns {void}
- */
- onShopSelectChange = (event, shopId) => {
- if (this.props.handleShopSelectChange) {
- this.props.handleShopSelectChange(event, shopId);
- }
- }
-
- renderEditButton() {
- const { editContainerItem } = this.props.navButtonStyles;
- return (
-
-
-
- );
- }
-
- /**
- * renderShopSelect
- * @method
- * @summary Handles shop options display on mobile view
- * @returns {JSX} React node containing dropdown menu
- */
- renderShopSelect() {
- if (this.props.handleShopSelectChange) {
- return (
-
- );
- }
- return null;
- }
-
- tagGroupProps = (tag) => {
- const subTagGroups = _.compact(TagHelpers.subTags(tag));
- const tagsByKey = {};
-
- if (Array.isArray(subTagGroups)) {
- for (const tagItem of subTagGroups) {
- tagsByKey[tagItem._id] = tagItem;
- }
- }
-
- return {
- parentTag: tag,
- tagsByKey: tagsByKey || {},
- tagIds: getTagIds({ tags: subTagGroups }) || [],
- subTagGroups
- };
- }
-
- render() {
- const { navbarOrientation, navbarPosition, navbarAnchor, navbarVisibility } = this.props;
- return (
-
-
-
- {this.props.children}
-
- {this.renderShopSelect()}
-
-
-
-
-
-
- {this.props.canEdit && this.renderEditButton()}
-
-
- );
- }
-}
-
-TagNav.propTypes = {
- canEdit: PropTypes.bool,
- children: PropTypes.node,
- closeNavbar: PropTypes.func,
- editable: PropTypes.bool, // eslint-disable-line react/boolean-prop-naming
- handleShopSelectChange: PropTypes.func,
- navButtonStyles: PropTypes.object,
- navbarAnchor: PropTypes.string,
- navbarOrientation: PropTypes.string,
- navbarPosition: PropTypes.string,
- navbarVisibility: PropTypes.string,
- onEditButtonClick: PropTypes.func,
- onMoveTag: PropTypes.func,
- selectedTag: PropTypes.object,
- shop: PropTypes.object,
- shops: PropTypes.array
-};
-
-export default TagNav;
diff --git a/imports/plugins/core/ui-tagnav/client/containers/tagNavContainer.js b/imports/plugins/core/ui-tagnav/client/containers/tagNavContainer.js
deleted file mode 100644
index 80e164ea3d..0000000000
--- a/imports/plugins/core/ui-tagnav/client/containers/tagNavContainer.js
+++ /dev/null
@@ -1,468 +0,0 @@
-import _ from "lodash";
-import update from "immutability-helper";
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-import { compose } from "recompose";
-import { Components, registerComponent, composeWithTracker } from "@reactioncommerce/reaction-components";
-import { Reaction, Router } from "/client/api";
-import { getTagIds } from "/lib/selectors/tags";
-import { TagHelpers } from "/imports/plugins/core/ui-tagnav/client/helpers";
-import getTagSuggestions from "/imports/plugins/core/ui-tagnav/client/util/getTagSuggestions";
-import { Tags } from "/lib/collections";
-import TagNav from "../components/tagNav";
-
-const navButtonStyles = {
- editContainerItem: {
- display: "flex",
- marginLeft: 5
- }
-};
-
-const NavbarStates = {
- Orientation: "stateNavbarOrientation",
- Position: "stateNavbarPosition",
- Anchor: "stateNavbarAnchor",
- Visible: "stateNavbarVisible"
-};
-
-const NavbarOrientation = {
- Vertical: "vertical",
- Horizontal: "horizontal"
-};
-
-const NavbarPosition = {
- Static: "static",
- Fixed: "fixed"
-};
-
-const NavbarAnchor = {
- Top: "top",
- Right: "right",
- Bottom: "bottom",
- Left: "left",
- None: "inline"
-};
-
-const TagNavHelpers = {
- onTagCreate(tagName, parentTag) {
- TagHelpers.createTag(tagName, undefined, parentTag);
- },
- onTagRemove(tag, parentTag) {
- TagHelpers.removeTag(tag, parentTag);
- },
- onTagSort(tagIds, parentTag) {
- TagHelpers.sortTags(tagIds, parentTag);
- },
- onTagDragAdd(movedTagId, toListId, toIndex, ofList) {
- TagHelpers.moveTagToNewParent(movedTagId, toListId, toIndex, ofList);
- },
- onUpdateTag(tagId, tagName, parentTagId) {
- TagHelpers.updateTag(tagId, tagName, parentTagId);
- },
- isMobile() {
- return window.matchMedia("(max-width: 991px)").matches;
- },
- tagById(tagId, tags) {
- return _.find(tags, (tag) => tag._id === tagId);
- },
- hasSubTags(tagId, tags) {
- const foundTag = this.tagById(tagId, tags);
-
- if (foundTag) {
- if (Array.isArray(foundTag.relatedTagIds) && foundTag.relatedTagIds.length) {
- return true;
- }
- }
- return false;
- }
-};
-
-const wrapComponent = (Comp) => (
- class TagNavContainer extends Component {
- static propTypes = {
- closeNavbar: PropTypes.func,
- editButton: PropTypes.node,
- editable: PropTypes.bool, // eslint-disable-line react/boolean-prop-naming
- hasEditRights: PropTypes.bool,
- isVisible: PropTypes.bool,
- tagIds: PropTypes.arrayOf(PropTypes.string),
- tagsAsArray: PropTypes.arrayOf(PropTypes.object),
- tagsByKey: PropTypes.object
- }
-
- constructor(props) {
- super(props);
-
- this._isMounted = false;
-
- this.state = {
- attachedBodyListener: false,
- editable: false,
- tagIds: props.tagIds || [],
- tagsByKey: props.tagsByKey || {},
- selectedTag: null,
- suggestions: [],
- [NavbarStates.Visible]: props.isVisible,
- newTag: {
- name: ""
- }
- };
-
- this.onWindowResize = this.onWindowResize.bind(this);
- }
-
- componentDidMount() {
- window.addEventListener("resize", this.onWindowResize);
- this.onWindowResize();
- this._isMounted = true;
- }
-
- // eslint-disable-next-line camelcase
- UNSAFE_componentWillReceiveProps(nextProps) {
- let selectedTag = {};
- const previousEdit = this.state.editable;
- nextProps.tagsAsArray.forEach((tag) => {
- if (this.isSelected(tag)) {
- selectedTag = tag;
- }
- });
-
- const { tagIds, tagsByKey, isVisible } = nextProps;
- this.setState({
- [NavbarStates.Visible]: isVisible,
- editable: previousEdit && this.canEdit,
- tagIds,
- tagsByKey,
- selectedTag
- });
- }
-
- componentWillUnmount() {
- window.removeEventListener("resize", this.onWindowResize);
- this._isMounted = false;
- }
-
- onWindowResize = () => {
- const matchQuery = window.matchMedia("(max-width: 991px)");
- if (matchQuery.matches) {
- this.setState({
- [NavbarStates.Orientation]: NavbarOrientation.Vertical,
- [NavbarStates.Position]: NavbarPosition.Fixed,
- [NavbarStates.Anchor]: NavbarAnchor.Left
- });
- } else {
- this.setState({
- [NavbarStates.Orientation]: NavbarOrientation.Horizontal,
- [NavbarStates.Position]: NavbarPosition.Static,
- [NavbarStates.Anchor]: NavbarAnchor.None,
- [NavbarStates.Visible]: false
- });
- }
- }
-
- canSaveTag(tag) {
- // Blank tags cannot be saved
- if (typeof tag.name === "string" && tag.name.trim().length === 0) {
- return false;
- }
-
- // If the tag does not have an id, then allow the save
- if (!tag._id) {
- return true;
- }
-
- // Get the original tag from the props
- // Tags from props are not mutated, and come from an outside source
- const originalTag = this.props.tagsByKey[tag._id];
-
- if (originalTag && originalTag.name !== tag.name) {
- return true;
- }
-
- return false;
- }
-
- handleNewTagSave = (tag, parentTag) => {
- if (this.canSaveTag(tag)) {
- TagNavHelpers.onTagCreate(tag.name, parentTag);
- this.setState({ newTag: { name: "" } });
- }
- }
-
- handleNewTagUpdate = (tag) => { // updates the current tag state being edited
- this.setState({
- newTag: tag
- });
- }
-
- handleTagRemove = (tag, parentTag) => {
- TagNavHelpers.onTagRemove(tag, parentTag);
- }
-
- handleTagUpdate = (tag) => {
- const newState = update(this.state, {
- tagsByKey: {
- [tag._id]: {
- $set: tag
- }
- }
- });
-
- this.setState(newState);
- }
-
- handleTagSave = (tag) => {
- TagNavHelpers.onUpdateTag(tag._id, tag.name);
- }
-
- handleMoveTag = (dragIndex, hoverIndex) => {
- const tag = this.state.tagIds[dragIndex];
-
- // Apply new sort order to variant list
- const newState = update(this.state, {
- tagIds: {
- $splice: [
- [dragIndex, 1],
- [hoverIndex, 0, tag]
- ]
- }
- });
-
- // Set local state so the component does't have to wait for a round-trip
- // to the server to get the updated list of variants
- this.setState(newState, () => {
- _.debounce(() => TagNavHelpers.onTagSort(this.state.tagIds), 500)(); // Save the updated positions
- });
- }
-
- handleGetSuggestions = async (suggestionUpdateRequest) => {
- const suggestions = await getTagSuggestions(
- suggestionUpdateRequest.value,
- { excludeTags: this.state.tagIds }
- );
-
- this.setState({ suggestions });
- }
-
- handleClearSuggestions = () => {
- this.setState({ suggestions: [] });
- }
-
- get canEdit() {
- return this.props.hasEditRights;
- }
-
- attachBodyListener = () => {
- document.body.addEventListener("mouseover", this.closeDropdown);
- this.setState({ attachedBodyListener: true });
- }
-
- detachhBodyListener = () => {
- document.body.removeEventListener("mouseover", this.closeDropdown);
- this.setState({ attachedBodyListener: false });
- }
-
- closeDropdown = (event) => {
- const closestNavigationItem = event.target.closest(".navbar-item");
-
- // on mouseover an element outside of tags, close dropdown
- if (this._isMounted && !closestNavigationItem) {
- this.closeDropdownTimeout = setTimeout(() => {
- this.setState({ selectedTag: null });
- this.detachhBodyListener();
- }, 500);
- } else if (this.closeDropdownTimeout) {
- clearTimeout(this.closeDropdownTimeout);
- }
- }
-
- get navbarOrientation() {
- return this.state[NavbarStates.Orientation];
- }
-
- get navbarPosition() {
- return this.state[NavbarStates.Position];
- }
-
- get navbarAnchor() {
- return this.state[NavbarStates.Anchor];
- }
-
- get navbarVisibility() {
- const isVisible = this.state[NavbarStates.Visible] === true;
-
- if (isVisible) {
- return "open";
- }
- return "closed";
- }
-
- onTagSelect = (currentSelectedTag) => {
- if (_.isEqual(currentSelectedTag, this.state.selectedTag)) {
- this.setState({ selectedTag: null });
- } else {
- this.setState({ selectedTag: currentSelectedTag });
- }
- }
-
- isSelected(tag) {
- let isSelected = false;
- if (this.state.selectedTag && tag) {
- isSelected = this.state.selectedTag._id === tag._id;
- }
- return isSelected;
- }
-
- handleTagMouseOver = (event, tag) => {
- const tagId = tag._id;
- const tags = this.props.tagsAsArray;
-
- if (TagNavHelpers.isMobile()) {
- return;
- }
- // While in edit mode, don't trigger the hover hide/show menu
- if (this.state.editable === false) {
- // User mode
- // Don't show dropdown if there are no subtags
- if (TagNavHelpers.hasSubTags(tagId, tags) === false) {
- this.setState({ selectedTag: null });
- return;
- }
-
- // Otherwise, show the menu
- // And Attach an event listener to the document body
- // This will check to see if the dropdown should be closed if the user
- // leaves the tag nav bar
- this.attachBodyListener();
- this.setState({ selectedTag: TagNavHelpers.tagById(tagId, tags) });
- }
- }
-
- handleTagClick = (event, tag) => {
- if (TagNavHelpers.isMobile()) {
- const tagId = tag._id;
- const tags = this.props.tagsAsArray;
- const { selectedTag } = this.state;
- const hasSubTags = TagNavHelpers.hasSubTags(tagId, tags);
-
- if (hasSubTags === false) {
- // click close button to make navbar left disappear
- this.props.closeNavbar();
- Router.go("tag", { slug: tag.slug });
- } else {
- event.preventDefault();
- }
-
- if (selectedTag && selectedTag._id === tagId) {
- this.setState({ selectedTag: null });
- } else if (hasSubTags) {
- this.setState({ selectedTag: TagNavHelpers.tagById(tagId, tags) });
- }
- } else {
- Router.go("tag", { slug: tag.slug });
- }
- }
-
- handleEditButtonClick = () => {
- this.setState({ editable: !this.state.editable });
- }
-
- hasDropdownClassName(tag) {
- if (Array.isArray(tag.relatedTagIds)) {
- return "has-dropdown";
- }
- return "";
- }
-
- navbarSelectedClassName = (tag) => {
- const currentSelectedTag = this.state.selectedTag;
-
- if (currentSelectedTag) {
- if (currentSelectedTag._id === tag._id) {
- return "selected";
- }
- }
- return "";
- }
-
- get tags() {
- if (this.state.editable) {
- return this.state.tagIds.map((tagId) => this.state.tagsByKey[tagId]);
- }
-
- return this.props.tagsAsArray;
- }
-
- render() {
- return (
-
-
-
-
- );
- }
- }
-);
-
-const composer = (props, onData) => {
- let tags = Tags.find({ isTopLevel: true }, { sort: { position: 1 } }).fetch();
- tags = _.sortBy(tags, "position"); // puts tags without position at end of array
-
- const tagsByKey = {};
-
- if (Array.isArray(tags)) {
- for (const tag of tags) {
- tagsByKey[tag._id] = tag;
- }
- }
-
- onData(null, {
- name: "coreHeaderNavigation",
- hasEditRights: Reaction.hasAdminAccess(),
- tagsAsArray: tags,
- isVisible: props.isVisible,
- tagIds: getTagIds({ tags }),
- tagsByKey
- });
-};
-
-registerComponent("TagNav", TagNav, [
- composeWithTracker(composer),
- wrapComponent
-]);
-
-export default compose(
- composeWithTracker(composer),
- wrapComponent
-)(TagNav);
diff --git a/imports/plugins/core/ui-tagnav/client/helpers/index.js b/imports/plugins/core/ui-tagnav/client/helpers/index.js
deleted file mode 100644
index b59f8bf032..0000000000
--- a/imports/plugins/core/ui-tagnav/client/helpers/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { TagHelpers } from "./tags";
diff --git a/imports/plugins/core/ui-tagnav/client/helpers/tags.js b/imports/plugins/core/ui-tagnav/client/helpers/tags.js
deleted file mode 100644
index a57d4825c6..0000000000
--- a/imports/plugins/core/ui-tagnav/client/helpers/tags.js
+++ /dev/null
@@ -1,178 +0,0 @@
-import _ from "lodash";
-import { Reaction, i18next } from "/client/api";
-import { Tags } from "/lib/collections";
-import { Meteor } from "meteor/meteor";
-import { Session } from "meteor/session";
-import { Template } from "meteor/templating";
-
-/**
- * @memberof Helpers
- * @summary Reaction TagNav shared helpers
- * @type {Object}
- */
-export const TagHelpers = {
- moveItem(oldArray, fromIndex, toIndex) {
- const newArray = [...oldArray];
- newArray.splice(toIndex, 0, newArray.splice(fromIndex, 1)[0]);
- return newArray;
- },
-
- subTags(parentTag) {
- if (_.isArray(parentTag.relatedTagIds)) {
- const tags = Tags.find({
- isTopLevel: false,
- _id: {
- $in: parentTag.relatedTagIds
- }
- }).fetch();
-
- const subTags = parentTag.relatedTagIds.map((tagId) => _.find(tags, (tagObject) => tagObject._id === tagId));
-
- return subTags;
- }
-
- return [];
- },
-
- currentTag() {
- return Session.get("currentTag");
- },
-
- getTags() {
- let tags = [];
-
- tags = Tags.find({
- isTopLevel: true
- }, {
- sort: {
- position: 1
- }
- }).fetch();
- /*
- if (this.tagIds) {
- for (let relatedTagId of this.tagIds) {
- if (!_.find(tags, {
- _id: relatedTagId
- })) {
- tags.push(Tags.findOne(relatedTagId));
- }
- }
- }*/
-
- if (this.tag) {
- Session.set("currentTag", this.tag._id);
- } else {
- Session.set("currentTag", "");
- }
-
- return tags;
- // there are cases where
- // we'll have no tags, and sort will error
- // so we check length for safety
- // if (tags) {
- // tags.sort(function (a, b) {
- // return a.position - b.position;
- // });
- // return tags;
- // }
- },
-
- createTag(tagName, tagId, parentTag) {
- if (!tagName) {
- return;
- }
- let parentTagId;
-
- if (parentTag) {
- parentTagId = parentTag._id;
- }
-
- Meteor.call("shop/updateHeaderTags", tagName, null, parentTagId, (error) => {
- if (error) {
- Alerts.toast(i18next.t("productDetail.tagExists"), "error");
- }
- });
- },
-
- updateTag(tagId, tagName, parentTagId) {
- Meteor.call("shop/updateHeaderTags", tagName, tagId, parentTagId, (error) => {
- if (error) {
- Alerts.toast(i18next.t("productDetail.tagExists"), "error");
- }
- });
- },
-
- /* eslint no-unused-vars: 0 */
- //
- // TODO review toIndex, ofList variable implementation in tags.js moveTagToNewParent
- //
- moveTagToNewParent(movedTagId, toListId, toIndex, ofList) {
- if (movedTagId) {
- if (toListId) {
- const result = Tags.update(toListId, {
- $addToSet: {
- relatedTagIds: movedTagId
- }
- });
-
- return result;
- }
-
- const result = Tags.update(movedTagId, {
- $set: {
- isTopLevel: true
- }
- });
-
- return result;
- }
- return 0;
- },
-
- sortTags(tagIds, parentTag) {
- if (_.isArray(tagIds)) {
- if (_.isEmpty(parentTag)) {
- // Top level tags
- for (const tagId of tagIds) {
- Tags.update(tagId, {
- $set: {
- position: tagIds.indexOf(tagId)
- }
- });
- }
- } else {
- // Sub tags
- Tags.update(parentTag._id, {
- $set: {
- relatedTagIds: _.compact(tagIds)
- }
- });
- }
- }
- },
-
- removeTag(tag, parentTag) {
- if (_.isEmpty(parentTag) === false) {
- Tags.update(parentTag._id, {
- $pullAll: {
- relatedTagIds: [tag._id]
- }
- });
- } else if (tag.isTopLevel === true) {
- Tags.update(tag._id, {
- $set: {
- isTopLevel: false
- }
- });
- }
- }
-};
-
-/**
- * @method reactionSubTags
- * @summary Template method to return subTags
- * @param parentTag {Object} Tag
- * @returns {Array} Array of subtags or empty Array
- * @memberof BlazeTemplateHelpers
- */
-Template.registerHelper("reactionSubTags", TagHelpers.subTags);
diff --git a/imports/plugins/core/ui-tagnav/client/index.js b/imports/plugins/core/ui-tagnav/client/index.js
deleted file mode 100644
index d0a5e8df30..0000000000
--- a/imports/plugins/core/ui-tagnav/client/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export { default as TagGroup } from "./components/tagGroup";
-export { default as TagGroupBody } from "./components/tagGroupBody";
-export { default as TagGroupHeader } from "./components/tagGroupHeader";
-export { default as TagNav } from "./components/tagNav";
-export { default as TagNavContainer } from "./containers/tagNavContainer";
diff --git a/imports/plugins/core/ui/client/containers/tagListContainer.js b/imports/plugins/core/ui/client/containers/tagListContainer.js
index 3ae7c19dcd..566575f892 100644
--- a/imports/plugins/core/ui/client/containers/tagListContainer.js
+++ b/imports/plugins/core/ui/client/containers/tagListContainer.js
@@ -9,7 +9,7 @@ import { Reaction, i18next } from "/client/api";
import TagList from "../components/tags/tagList";
import { Tags } from "/lib/collections";
import { getTagIds } from "/lib/selectors/tags";
-import getTagSuggestions from "/imports/plugins/core/ui-tagnav/client/util/getTagSuggestions";
+import getTagSuggestions from "../helpers/getTagSuggestions";
const wrapComponent = (Comp) => (
class TagListContainer extends Component {
diff --git a/imports/plugins/core/ui-tagnav/client/util/getTagSuggestions.js b/imports/plugins/core/ui/client/helpers/getTagSuggestions.js
similarity index 100%
rename from imports/plugins/core/ui-tagnav/client/util/getTagSuggestions.js
rename to imports/plugins/core/ui/client/helpers/getTagSuggestions.js