Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move some core files to new shop plugin #5233

Merged
merged 5 commits into from
Jun 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 24 additions & 88 deletions client/modules/core/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import _ from "lodash";
import store from "store";
import { Accounts as MeteorAccounts } from "meteor/accounts-base";
import { Meteor } from "meteor/meteor";
import { Session } from "meteor/session";
Expand All @@ -11,7 +10,7 @@ import { Roles } from "meteor/alanning:roles";
import Logger from "/client/modules/logger";
import { Countries } from "/client/collections";
import { localeDep } from "/client/modules/i18n";
import { Packages, Shops, Accounts } from "/lib/collections";
import { Packages, Shops } from "/lib/collections";
import { Router } from "/client/modules/router";
import { DomainsMixin } from "./domains";
import { getUserId } from "./helpers/utils";
Expand All @@ -28,8 +27,6 @@ const reactionState = new ReactiveDict();

export const userPrefs = new ReactiveVar(undefined, (val, newVal) => JSON.stringify(val) === JSON.stringify(newVal));

const deps = new Map();

// Slugify is imported when Reaction.getSlug is called
let slugify;

Expand Down Expand Up @@ -135,7 +132,7 @@ export default {
});

// Listen for active shop change
return Tracker.autorun(() => {
return Tracker.autorun(() => { // eslint-disable-line consistent-return
if (this.Subscriptions.MerchantShops.ready()) {
// if we don't have an active shopId, try to retrieve it from the userPreferences object
// and set the shop from the storedShopId
Expand Down Expand Up @@ -280,7 +277,7 @@ export default {

//
// actual logic block to check permissions
// we'll bypass unecessary checks during
// we'll bypass unnecessary checks during
// a user logging, as we'll check again
// when everything is ready
//
Expand Down Expand Up @@ -411,63 +408,6 @@ export default {
return this.getShopId();
},

/**
* @name getUserPreferences
* @method
* @memberof Core/Client
*/
getUserPreferences(packageName, preference, defaultValue) {
getDep(`${packageName}.${preference}`).depend();
if (Meteor.user()) {
const packageSettings = store.get(packageName);
// packageSettings[preference] should not be undefined or null.
if (packageSettings && typeof packageSettings[preference] !== "undefined" && packageSettings[preference] !== null) {
return packageSettings[preference];
}
}

return defaultValue || undefined;
},

/**
* @name setUserPreferences
* @method
* @memberof Core/Client
*/
setUserPreferences(packageName, preference, value) {
getDep(`${packageName}.${preference}`).changed();
// User preferences are not stored in Meteor.user().profile
// to prevent all autorun() with dependency on Meteor.user() to run again.
if (Meteor.user()) {
// "reaction" package settings should be synced to
// the Accounts collection.
const syncedPackages = ["reaction"];
if (syncedPackages.indexOf(packageName) > -1) {
Accounts.update(getUserId(), {
$set: {
[`profile.preferences.${packageName}.${preference}`]: value
}
});
}
}
const packageSettings = store.get(packageName) || {};
packageSettings[preference] = value;
return store.set(packageName, packageSettings);
},

/**
* @name updateUserPreferences
* @method
* @memberof Core/Client
*/
updateUserPreferences(packageName, preference, values) {
const currentPreference = this.getUserPreferences(packageName, preference, {});
return this.setUserPreferences(packageName, preference, {
...currentPreference,
...values
});
},

/**
* primaryShopId is the first created shop. In a marketplace setting it's
* the shop that controls the marketplace and can see all other shops.
Expand Down Expand Up @@ -542,7 +482,7 @@ export default {
*/
getCurrentShop() {
// Give preference to shop chosen by the user
const activeShopId = this.getUserPreferences("reaction", "activeShopId");
const activeShopId = this.getUserShopId();
if (activeShopId) return Shops.findOne({ _id: activeShopId });

// If no chosen shop, look up the shop by domain
Expand All @@ -554,6 +494,20 @@ export default {
return shop;
},

/**
* @name getUserShopId
* @method
* @memberof Core/Client
* @summary Get current user's shop ID, as stored in preferences
* @return {String} active shop ID
*/
getUserShopId() {
const preferences = userPrefs.get(); // reactivity on `profile.preferences` changes only
if (!preferences) return null;

return _.get(preferences, "reaction.activeShopId");
},

/**
* shopId refers to the active shop. For most shoppers this will be the same
* as the primary shop, but for administrators this will usually be the shop
Expand All @@ -574,7 +528,7 @@ export default {
* @memberof Core/Client
*/
getShopId() {
return this.shopId || this.getUserPreferences("reaction", "activeShopId");
return this.shopId || this.getUserShopId();
},

/**
Expand All @@ -600,9 +554,7 @@ export default {
if (!id || this.shopId === id) { return; }

this.shopId = id;
this.setUserPreferences("reaction", "activeShopId", id);

Meteor.call("shop/resetShopId");
Meteor.call("accounts/setActiveShopId", id);
},

/**
Expand Down Expand Up @@ -661,7 +613,7 @@ export default {
// If slugify/transliteration is loaded & no lang change
return;
} else if (latinLangs.indexOf(lang) >= 0) {
// If shop's language uses latin based chars, load slugify, else load transliterations's slugify
// If shop's language uses latin based chars, load slugify, else load transliteration's slugify
mod = await import("slugify");
} else {
mod = await import("transliteration");
Expand Down Expand Up @@ -1079,11 +1031,11 @@ function createCountryCollection(countries) {
});
}
}
countryOptions.sort((a, b) => {
if (a.label < b.label) {
countryOptions.sort((itemA, itemB) => {
if (itemA.label < itemB.label) {
return -1;
}
if (a.label > b.label) {
if (itemA.label > itemB.label) {
return 1;
}
return 0;
Expand All @@ -1094,19 +1046,3 @@ function createCountryCollection(countries) {
}
return countryOptions;
}

/**
* Gets the dependency for the key if available, else creates
* a new dependency for the key and returns it.
* @name getDep
* @method
* @param {String} - The key to get the dependency for
* @returns {Tracker.Dependency}
* @private
*/
function getDep(key) {
if (!deps.has(key)) {
deps.set(key, new Tracker.Dependency());
}
return deps.get(key);
}
32 changes: 1 addition & 31 deletions client/modules/core/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import store from "store";
import Random from "@reactioncommerce/random";
import { Meteor } from "meteor/meteor";
import { Tracker } from "meteor/tracker";
import { Accounts as AccountsCollection } from "/lib/collections";
import { Accounts } from "meteor/accounts-base";

import { Reaction, Logger } from "/client/api";
import { Reaction } from "/client/api";
import { userPrefs } from "./main";
import { getUserId } from "./helpers/utils";

Expand Down Expand Up @@ -42,35 +41,6 @@ Tracker.autorun(() => {
});
});

Tracker.autorun(() => {
const userId = getUserId(); // The only reactive thing in this autorun. Reruns on login/logout only.
if (!userId) return;

// Load data from Accounts collection into the localStorage
Tracker.nonreactive(() => {
// Don't load the data from Accounts Collection again when something changes
// as we are already storing everything in the localStorage reactively
try {
const user = AccountsCollection.findOne(userId);
if (user && user.profile && user.profile.preferences) {
Object.keys(user.profile.preferences).forEach((packageName) => {
const packageSettings = user.profile.preferences[packageName];
Object.keys(packageSettings).forEach((preference) => {
if (packageName === "reaction" && preference === "activeShopId") {
// Because activeShopId is cached on client side.
Reaction.setShopId(packageSettings[preference]);
} else {
Reaction.setUserPreferences(packageName, preference, packageSettings[preference]);
}
});
});
}
} catch (err) {
Logger.error("Problem in loading user preferences from Accounts collection");
}
});
});

// Fine-grained reactivity on only the user preferences
Tracker.autorun(() => {
const userId = getUserId();
Expand Down
2 changes: 0 additions & 2 deletions imports/node-app/devserver/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import accounts from "/imports/plugins/core/accounts/server/no-meteor/queries";
import address from "/imports/plugins/core/address/server/no-meteor/queries";
import cart from "/imports/plugins/core/cart/server/no-meteor/queries";
import catalog from "/imports/plugins/core/catalog/server/no-meteor/queries";
import core from "/imports/plugins/core/core/server/no-meteor/queries";
import inventory from "/imports/plugins/core/inventory/server/no-meteor/queries";
import navigation from "/imports/plugins/core/navigation/server/no-meteor/queries";
import shipping from "/imports/plugins/core/shipping/server/no-meteor/queries";
Expand All @@ -22,7 +21,6 @@ export default merge(
address,
cart,
catalog,
core,
inventory,
navigation,
shipping,
Expand Down
2 changes: 2 additions & 0 deletions imports/node-app/devserver/registerPlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import registerNavigationPlugin from "/imports/plugins/core/navigation/server/no
import registerOrdersPlugin from "/imports/plugins/core/orders/server/no-meteor/register";
import registerProductPlugin from "/imports/plugins/core/product/server/no-meteor/register";
import registerSettingsPlugin from "/imports/plugins/core/settings/server/register";
import registerShopPlugin from "/imports/plugins/core/shop/server/register";
import registerTagsPlugin from "/imports/plugins/core/tags/server/no-meteor/register";
import registerTemplatesPlugin from "/imports/plugins/core/templates/server/no-meteor/register";
import registerNotificationsPlugin from "/imports/plugins/included/notifications/server/no-meteor/register";
Expand All @@ -30,6 +31,7 @@ export default async function registerPlugins(app) {
await registerFilesPlugin(app); // Core plugin needs Media collection, so files plugin must be first
await registerCorePlugin(app);
await registerAccountsPlugin(app);
await registerShopPlugin(app);
await registerCartPlugin(app);
await registerCatalogPlugin(app);
await registerDiscountsPlugin(app);
Expand Down
2 changes: 2 additions & 0 deletions imports/plugins/core/accounts/server/methods/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import inviteShopOwner from "./inviteShopOwner";
import removeEmailAddress from "./removeEmailAddress";
import removeUserPermissions from "./removeUserPermissions";
import sendResetPasswordEmail from "./sendResetPasswordEmail";
import setActiveShopId from "./setActiveShopId";
import setProfileCurrency from "./setProfileCurrency";
import setUserPermissions from "./setUserPermissions";
import updateEmailAddress from "./updateEmailAddress";
Expand Down Expand Up @@ -39,6 +40,7 @@ export default {
"accounts/removeEmailAddress": removeEmailAddress,
"accounts/removeUserPermissions": removeUserPermissions,
"accounts/sendResetPasswordEmail": sendResetPasswordEmail,
"accounts/setActiveShopId": setActiveShopId,
"accounts/setProfileCurrency": setProfileCurrency,
"accounts/setUserPermissions": setUserPermissions,
"accounts/updateEmailAddress": updateEmailAddress,
Expand Down
27 changes: 27 additions & 0 deletions imports/plugins/core/accounts/server/methods/setActiveShopId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { check } from "meteor/check";
import { Accounts } from "/lib/collections";
import Reaction from "/imports/plugins/core/core/server/Reaction";

/**
* @name accounts/setActiveShopId
* @memberof Accounts/Methods
* @method
* @param {String} shopId Shop ID to make active for the current user
* @summary Sets users profile currency
* @returns {Object} Account document
*/
export default function setActiveShopId(shopId) {
check(shopId, String);

const userId = Reaction.getUserId();
if (userId) {
Accounts.update({ userId }, {
$set: {
"profile.preferences.reaction.activeShopId": shopId
}
});

// Clear the shop ID that is cached on this connection
Reaction.resetShopId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import administrators from "./administrators";
import groups from "./groups";
import roles from "./roles";

export default {
administrators,
groups,
roles
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AddAccountAddressBookEntryPayload from "./AddAccountAddressBookEntryPaylo
import Group from "./Group";
import Mutation from "./Mutation";
import Query from "./Query";
import Shop from "./Shop";

/**
* Account-related GraphQL resolvers
Expand All @@ -16,6 +17,7 @@ export default {
Group,
Mutation,
Query,
Shop,
...getConnectionTypeResolvers("Account"),
...getConnectionTypeResolvers("Group"),
...getConnectionTypeResolvers("Role")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ type SetAccountProfileCurrencyPayload {
clientMutationId: String
}

extend type Shop {
"""
Returns a list of administrators for this shop, as a Relay-compatible connection.
"Administrators" means all linked accounts that have the "admin" role for this shop.
"""
administrators(after: ConnectionCursor, before: ConnectionCursor, first: ConnectionLimitInt, last: ConnectionLimitInt, sortOrder: SortOrder = asc, sortBy: AccountSortByField = createdAt): AccountConnection
}

extend type Mutation {
"Add a new address to the `addressBook` field for an account"
addAccountAddressBookEntry(input: AddAccountAddressBookEntryInput!): AddAccountAddressBookEntryPayload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ type RemoveGroupPayload {
wasRemoved: Boolean!
}

extend type Shop {
"Returns a list of groups for this shop, as a Relay-compatible connection."
groups(after: ConnectionCursor, before: ConnectionCursor, first: ConnectionLimitInt, last: ConnectionLimitInt, sortOrder: SortOrder = asc, sortBy: GroupSortByField = createdAt): GroupConnection
}

extend type Mutation {
"Add an account to a group"
addAccountToGroup(input: AddAccountToGroupInput!): AddAccountToGroupPayload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ type RoleEdge implements NodeEdge {
node: Role
}

extend type Shop {
"Returns a list of roles for this shop, as a Relay-compatible connection."
roles(after: ConnectionCursor, before: ConnectionCursor, first: ConnectionLimitInt, last: ConnectionLimitInt, sortOrder: SortOrder = asc, sortBy: RoleSortByField = name): RoleConnection
}

extend type Query {
"Returns a paged list of all roles associated with a shop"
roles(shopId: ID!, after: ConnectionCursor, before: ConnectionCursor, first: ConnectionLimitInt, last: ConnectionLimitInt, sortOrder: SortOrder = asc, sortBy: RoleSortByField = name): RoleConnection
Expand Down
Loading