Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@dancastellon
Copy link
Contributor

@dancastellon dancastellon commented Sep 25, 2018

Resolves #4682 and #4418
Impact: major
Type: feature

Issue

Currently Reaction's navigation only supports tags. We need a way to define and load a navigation that supports both tags and arbitrary links.

Solution

This PR introduces 2 new collections - NavigationTrees and NavigationItems - as well as a GraphQL backend for defining and loading trees and items.

Breaking changes

None

Testing

Migration that creates a default navigation

On first startup, a default navigation tree with a single "Home" item will be created for each shop in the database. To confirm, follow these steps:

  1. View the NavigationTrees collection and confirm 1 document for each shopId
  2. Confirm name = "Main Navigation"
  3. Confirm both the draftItems and items fields are arrays with a single item:
[
  {
    navigationItemId: ...
  }
]
  1. View the NavigationItems collection and confirm 1 "Home" item for each navigation tree:
{
  _id: ...,
  data: {
    content: [{
      language: "en",
      value: "Home"
    }],
    url: "/",
    isUrlRelative: true,
    shouldOpenInNewWindow: false
  }
  draftData: { ...same as data },
  createdAt: ...date,
  hasUnpublishedChanges: false
}

Shop queries to load defaultNavigationTreeId and defaultNavigationTree

Two new queries are added to the primaryShop query - defaultNavigationTreeId and defaultNavigationTree. To confirm:

  1. In Graphiql, run this query and confirm you get an ID back:
{
  primaryShop {
    defaultNavigationTreeId
  }
}
  1. Run this query to confirm you can load the default navigation tree's structure:
{
  primaryShop {
    defaultNavigationTree(language: "en") {
      items {
        navigationItem {
          data {
          	content {
              value
            }
            classNames
            url
            isUrlRelative
            shouldOpenInNewWindow
        	}
        }
      }
    }
  }
}

Mutation to create a navigation item

  1. Run this query in Graphiql, while logged in as an admin:
Query:
mutation createNavigationItem($input: CreateNavigationItemInput!) {
  createNavigationItem(input: $input) {
    navigationItem {
      _id
      shopId
      data {
        content {
          language
          value
        }
        classNames
        url
        isUrlRelative
        shouldOpenInNewWindow
      }
      draftData {
	content {
          language
          value
        }
        classNames
        url
        isUrlRelative
        shouldOpenInNewWindow
      }
      createdAt
      metadata
      hasUnpublishedChanges
    }
  }
}

Variables:
{
  "input": {
    "navigationItem": {
      "draftData": {
	"content": [{
          "language": "en",
          "value": "About"
        }],
        "url": "/about",
      	"isUrlRelative": true,
        "shouldOpenInNewWindow": false,
        "classNames": "about-link"
      },
      "metadata": "{\"tagId\": \"cseCBSSrJ3t8HQSNP\"}"
    }
  }
}
  1. Confirm the item was created in the NavigationItems collection

Operator query to load navigation items

  1. Run this query to get the primary shopId
{
  primaryShopId
}
  1. Using the returned ID, run this query:
{
  navigationItemsByShopId(shopId:"ID_HERE"){
    pageInfo {
      hasNextPage
    }
    totalCount
    edges {
      cursor
      node {
        _id
	createdAt
        metadata
        draftData {
	  content {
	    language
            value
          }
          isUrlRelative
          shouldOpenInNewWindow
          url
          classNames
        }
      }
    }
    nodes {
      _id
    }
  }
}
  1. Confirm navigation items are returned, newest first. Add sortOrder: asc to query args (after shopId) to return oldest first

Update Navigation Item mutation

  1. Run the same mutation under "Mutation to create a navigation item" again. At this point you'll have 2 navigation items titled "About".
  2. Copy the _id returned, and run the query below to update the navigation item to "Team" with a Spanish translation:
Query:
mutation updateNavigationItem($input: UpdateNavigationItemInput!) {
  updateNavigationItem(input: $input) {
    navigationItem {
      _id
      shopId
      data {
        content {
          language
          value
        }
        classNames
        url
        isUrlRelative
        shouldOpenInNewWindow
      }
      draftData {
	content {
          language
          value
        }
        classNames
        url
        isUrlRelative
        shouldOpenInNewWindow
      }
      createdAt
      metadata
      hasUnpublishedChanges
    }
  }
}

Variables:
{
  "input": {
    "_id": "ID_HERE",
    "navigationItem": {
      "draftData": {
          "content": [{
            "language": "en",
           "value": "Team"
         }, {
            "language": "es",
            "value": "Equipo"
        }],
        "url": "/team",
      	"isUrlRelative": true,
        "shouldOpenInNewWindow": true,
        "classNames": "team-link"
      }
    }
  }
}

Delete navigation item mutation

  1. Run the same mutation under "Mutation to create a navigation item" again.
  2. Copy the _id
  3. Run this query to delete the newly created item:
Query:
mutation deleteNavigationItem($input: DeleteNavigationItemInput!) {
  deleteNavigationItem(input: $input) {
    navigationItem {
      _id
    }
  }
}

Variables:
{
  "input": {
    "_id": "ID_HERE"
  }
}

Update navigation tree mutation

  1. Run this query to get the primary shop's navigation tree ID. Copy it for later.
{
  primaryShop {
    defaultNavigationTreeId
  }
}
  1. Run the 2 queries from "Operator query to load navigation items" to get the _ids of the 3 navigation items currently in the DB. Copy all 3 _ids.
  2. Using the tree _id and 3 navigation item _ids, run this query to add the items to the tree:
Query:
mutation updateNavigationTree($input: UpdateNavigationTreeInput!) {
  updateNavigationTree(input: $input) {
    navigationTree {
      _id
      shopId
      name
      draftItems {
        navigationItem {
          _id
        }
        items {
          navigationItem {
            _id
          }
          items {
            navigationItem {
              _id
            }
          }
        }
      }
      hasUnpublishedChanges
    }
  }
}

Variables:
{
  "input": {
    "_id": "TREE_ID_HERE",
    "navigationTree": {
      "draftItems": [
      	{
          "navigationItemId": "ITEM_1_ID_HERE",
          "items": [
            {
              "navigationItemId": "ITEM_2_ID_HERE",
              "items": [
                {
                  "navigationItemId": "ITEM_3_ID_HERE"
                }
              ]
            }
          ]
        }
      ]
    }
  }
}

Publish navigation changes mutation

This mutation publishes changes to the tree structure, and any content changes on items in the tree. 1. Confirm in DB that 2 of the navigation items you created have empty data arrays and hasUnpublishedChanges = true
2. Confirm the navigation tree itself has only 1 element in its items array. This is the "Home" item that was created by the migration
3. Run this query to publish changes:

Query:
mutation publishNavigationChanges($input: PublishNavigationChangesInput!) {
  publishNavigationChanges(input: $input) {
    navigationTree {
      _id
      shopId
      name
      draftItems {
        navigationItem {
          _id
        }
        items {
          navigationItem {
            _id
          }
          items {
            navigationItem {
              _id
            }
          }
        }
      }
      hasUnpublishedChanges
    }
  }
}

Variables:
{
  "input": {
    "_id": "ID_HERE"
  }
}
  1. Confirm in the DB that the tree's draftItems were copied to items and that hasUnpublishedChanges = false
  2. Confirm draftData has been copied to data and hasPublishedChanges = false for all navigation items

Load navigation tree query

  1. Run this query to load the navigation tree structure, in English:
{
	navigationTreeById(
    id: "cmVhY3Rpb24vbmF2aWdhdGlvblRyZWU6cXRrbWpFSlByaEo3Zldia2E=",
    language: "en"
  ) {
    _id
    shopId
    name
    items {
			navigationItem {
        data {
          ...NavigationItemFields
        }
      }
      items {
        navigationItem {
          data {
            ...NavigationItemFields
          }
        }
        items {
          navigationItem {
            data {
              ...NavigationItemFields
            }
          }
        }
      }
    }
  }
}

fragment NavigationItemFields on NavigationItemData {
  content {
    language
    value
  }
  classNames
  url
  isUrlRelative
  shouldOpenInNewWindow
}
  1. Change the "language" argument to Spanish and rerun the query
  2. Confirm for items that have a Spanish translation, the content is returned in Spanish ("/team"). Should default to English if no translation is available

@dancastellon dancastellon changed the title [WIP] feat: improved navigation (title tbd) [WIP] feat: navigation builder Oct 8, 2018
@spencern
Copy link
Contributor

spencern commented Nov 5, 2018

@dancastellon is this still in progress?

@dancastellon
Copy link
Contributor Author

@spencern It is, but only in between some of my enterprise client work. I'm close to being finished on a task for a client. I'll checkin with @zenweasel as to whether I can make more progress here or should focus on another client task.

@dancastellon dancastellon changed the base branch from master to release-2.0.0-rc.6 November 9, 2018 14:30
@impactmass impactmass changed the base branch from release-2.0.0-rc.7 to release-2.0.0-rc.8 November 30, 2018 16:13
@mikemurray
Copy link
Member

@dancastellon What's the current status of this PR?

@dancastellon
Copy link
Contributor Author

@mikemurray This is ready for review. Thanks!

@mikemurray
Copy link
Member

@dancastellon There are still some outstanding comments from @aldeed that are marked as outdated but are not resolved.

@dancastellon
Copy link
Contributor Author

@mikemurray Updated

@mikemurray
Copy link
Member

@aldeed Do you have any more things to review on this PR?

@aldeed
Copy link
Contributor

aldeed commented Dec 6, 2018

@dancastellon @mikemurray Some GraphQL integration tests are failing on CI. Let me know if you need help debugging.

@dancastellon
Copy link
Contributor Author

@aldeed I fixed the integration tests, but in CI I'm getting this error - Error: listen EADDRINUSE :::4041. Locally the tests - addAccountAddressBookEntry.test.js - are all passing. Have you seen this before?

@aldeed
Copy link
Contributor

aldeed commented Dec 13, 2018

@dancastellon I don't know why that happens but I've seen in locally sometimes, too. The free port finder finds a non-free port. It only has one job and it can't even do that properly! 😄

Anyway, I plan to rewrite how that works, which should fix it. For now, feel free to ignore

@aldeed aldeed requested a review from mikemurray December 13, 2018 22:30
Copy link
Contributor

@aldeed aldeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have only skimmed this since my initial review, but I'll let @mikemurray do the final review

Copy link
Member

@mikemurray mikemurray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants