Adding first stripe example
utils methods are here, using native/zepto instead of lodash
This commit is contained in:
parent
0d316f14e0
commit
892b43c90e
5 changed files with 519 additions and 115 deletions
232
dev/index.html
232
dev/index.html
|
|
@ -1,19 +1,225 @@
|
||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
<title>Documentation</title>
|
||||||
<title>documentationsearch.js</title>
|
<link rel="stylesheet" type="text/css" href="/stripe.css" media="screen" />
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="shortcut icon" href="favicon.ico">
|
||||||
<!--[if lte IE 9]>
|
|
||||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
|
|
||||||
<![endif]-->
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
|
||||||
<h1>documentationsearch.js</h1>
|
|
||||||
<h2>Search in docs: <input type="text" id="search-input" /></h2>
|
|
||||||
|
|
||||||
<script src="bundle.js"></script>
|
<body id="documentation">
|
||||||
|
|
||||||
|
<div id="header">
|
||||||
|
<h1><a href="index.html">Stripe</a></h1>
|
||||||
|
<div class="navigation">
|
||||||
|
<div class="signin"><a id='signin' href="https://dashboard.stripe.com/login"><span>Sign In</span></a></div>
|
||||||
|
|
||||||
|
<ul class="global">
|
||||||
|
<li><input type="text" id="search-input" /></li>
|
||||||
|
<li><a href="country%3Fcountry=CH&redirect=%252Fdocs.html" class="selected">Documentation</a></li>
|
||||||
|
<li><a href="https://support.stripe.com">Help & Support</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- #header -->
|
||||||
|
|
||||||
|
<section id="doc">
|
||||||
|
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
|
||||||
|
<h1 class="references">Development</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="selected"><a href="country%3Fcountry=CH&redirect=%252Fdocs.html">Getting Started</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/tutorials/checkout.html">Embedded Form</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/tutorials/forms.html">Custom Forms</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/mobile.html">Mobile Apps</a></li>
|
||||||
|
<li class="unselected"><a href="docs/tutorials/charges.html">Charging Cards</a></li>
|
||||||
|
<li class="unselected"><a href="docs/testing.html">Testing</a></li>
|
||||||
|
<li class="unselected"><a href="help/security.html">Security</a></li>
|
||||||
|
<li class="unselected"><a href="docs/fraud.html">Fraud Protection</a></li>
|
||||||
|
<li class="unselected"><a href="docs/webhooks.html">Webhooks</a></li>
|
||||||
|
<li class="unselected"><a href="docs/guides/bitcoin.html">Bitcoin Guide</a></li>
|
||||||
|
<li class="unselected"><a href="docs/guides/alipay.html">Alipay Guide</a></li>
|
||||||
|
<li class="unselected"><a href="docs/guides/file-upload.html">File Upload Guide</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h1 class="getting-started">Account</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="unselected"><a href="docs/tutorials/dashboard.html">Your Account</a></li>
|
||||||
|
<li class="unselected"><a href="help/transfers.html">Getting Paid</a></li>
|
||||||
|
<li class="unselected"><a href="help/disputes-overview.html">Disputes</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/guides/dispute-evidence.html">Submitting Evidence</a></li>
|
||||||
|
<li class="unselected sub"><a href="help/dispute-types.html">Dispute Types</a></li>
|
||||||
|
<li class="unselected sub"><a href="help/disputes.html">Disputes FAQ</a></li>
|
||||||
|
<li class="unselected"><a href="docs/integrations.html">Integrations</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h1 class="faq">References</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="unselected"><a href="docs/examples.html">Examples</a></li>
|
||||||
|
<li class="unselected"><a href="docs/stripe.js.html">Stripe.js</a></li>
|
||||||
|
<li class="unselected"><a href="docs/checkout.html">Checkout</a></li>
|
||||||
|
<li class="unselected"><a href="docs/libraries.html">API Libraries</a></li>
|
||||||
|
<li class="unselected"><a href="docs/upgrades.html">API Upgrades</a></li>
|
||||||
|
|
||||||
|
<li class="unselected">
|
||||||
|
<a href="docs/api.html" class="external" target="_blank">Full API Reference</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h1 class="subscriptions">Subscriptions</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="unselected"><a href="docs/subscriptions.html">Overview</a></li>
|
||||||
|
<li class="unselected"><a href="docs/tutorials/subscriptions.html">Getting Started</a></li>
|
||||||
|
<li class="unselected"><a href="docs/guides/subscriptions.html">Integration Guide</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h1 class="orders">Relay</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="unselected"><a href="docs/relay.html">Overview</a></li>
|
||||||
|
<li class="unselected"><a href="docs/relay/apps-guide.html">Apps Guide</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h1 class="connect">Connect</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="unselected"><a href="docs/connect.html">Overview</a></li>
|
||||||
|
<li class="unselected"><a href="docs/connect/connecting-to-accounts.html">Connecting to Accounts</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/connect/standalone-accounts.html">Standalone Accounts</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/connect/authentication.html">Authentication</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/connect/reference.html">OAuth Reference</a></li>
|
||||||
|
<li class="unselected"><a href="docs/connect/payments-fees.html">Payments and Fees</a></li>
|
||||||
|
<li class="unselected"><a href="docs/connect/special-case-transfers.html">Special-case Transfers</a></li>
|
||||||
|
<li class="unselected"><a href="docs/connect/managed-accounts.html">Managed Accounts</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/connect/updating-accounts.html">Updating Accounts</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/connect/identity-verification.html">Identity Verification</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/connect/bank-transfers.html">Bank Transfers</a></li>
|
||||||
|
<li class="unselected sub"><a href="docs/connect/migrating.html">Migrating Recipients</a></li>
|
||||||
|
<li class="unselected"><a href="docs/connect/testing.html">Testing</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h1 class="more">About Stripe</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="unselected"><a href="help/contact.html">Contact</a></li>
|
||||||
|
<li class="unselected"><a href="global.html">Global Users</a></li>
|
||||||
|
<li class="unselected last"><a href="gallery.html">Gallery</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<section id="content">
|
||||||
|
<section id="start">
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<h1>Getting Started</h1>
|
||||||
|
<p>
|
||||||
|
Below you'll find tutorials that will teach you how to use Stripe, and reference documentation for all the moving parts.
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="getting-started">
|
||||||
|
|
||||||
|
<div class="implementation-options">
|
||||||
|
|
||||||
|
<div class="guides">
|
||||||
|
<a class="web" href="docs/tutorials/checkout.html">
|
||||||
|
<h2>On your website</h2>
|
||||||
|
<p>
|
||||||
|
Start accepting payments on your website with our JavaScript libraries. <span class="arrow">Learn more</span>
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
<a class="mobile" href="docs/mobile.html">
|
||||||
|
<h2>In your mobile app</h2>
|
||||||
|
<p>
|
||||||
|
We have toolkits for native iPhone and Android applications. <span class="arrow">Learn more</span>
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="payment-types">
|
||||||
|
<h3>Accept different payment types</h3>
|
||||||
|
<p>
|
||||||
|
In addition to charging <a href="docs/tutorials/charges.html">credit and debit cards</a>, Stripe's APIs let you accept payments on <a href="docs/mobile/android.html">Android</a> and <a href="docs/mobile/ios.html">iOS</a>. You can also support <a href="docs/guides/bitcoin.html">Bitcoin</a>, <a href="docs/guides/alipay.html">Alipay</a>, or <a href="docs/guides/amex-express-checkout.html">Amex Express Checkout</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="non-developer">
|
||||||
|
<a class="platforms" href="docs/libraries.html#third-party-plugins">
|
||||||
|
<h3>Stripe plugins for 3rd party software</h3>
|
||||||
|
<p>
|
||||||
|
As well as the official API libraries listed above, there are a number of third-party plugins and libraries built by our community, such as for WordPress and Drupal.
|
||||||
|
|
||||||
|
<span class="arrow">Learn more</span>
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a class="services" href="docs/integrations.html">
|
||||||
|
<h3>Use Stripe with other services</h3>
|
||||||
|
<p>
|
||||||
|
Stripe has lots of third-party integrations which require no programming, hosting or complicated setup on your behalf, such as Shopify and Wufoo.
|
||||||
|
|
||||||
|
<span class="arrow">Learn more</span>
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section id="details">
|
||||||
|
<article>
|
||||||
|
<hr>
|
||||||
|
<h2>Need help?</h2>
|
||||||
|
<p>We're always happy to help out with code or any other questions you might have. <a href="https://support.stripe.com" class="arrow">Learn more</a></p>
|
||||||
|
|
||||||
|
<h2>API mailing list</h2>
|
||||||
|
<p>Join our mailing list to be notified of API changes and stay up to date. <a href="https://groups.google.com/a/lists.stripe.com/forum/#!forum/api-discuss" class="arrow">View mailing list</a></p>
|
||||||
|
|
||||||
|
<h2>Resources</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="docs/libraries.html">API libraries</a></li>
|
||||||
|
<li><a href="docs/examples.html">Example projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class="clearfix">
|
||||||
|
<section class="questions">
|
||||||
|
<h1>Questions?</h1>
|
||||||
|
<p>We're always happy to help with code or other questions you might have! Check out our answers to <a href="https://support.stripe.com">common questions</a> or chat live with other developers in <a href="irc://irc.freenode.net/stripe">#stripe</a> on freenode.</p>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</footer>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- #documentation -->
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
|
||||||
|
<p><a href="index.html">© Stripe</a></p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://status.stripe.com"><span>System Status</span></a></li>
|
||||||
|
<li><a href="about.html">About</a></li>
|
||||||
|
<li><a href="blog.html"><span>Blog</span></a></li>
|
||||||
|
<li><a href="jobs.html"><span>Jobs</span></a></li>
|
||||||
|
<li><a href="http://twitter.com/stripe">Twitter</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul class="lesser">
|
||||||
|
<li><a href="terms.html">Terms of Service</a></li>
|
||||||
|
<li><a href="privacy.html">Privacy Policy</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="country-dropdown-overlay"></div>
|
||||||
|
|
||||||
|
<script src="/bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
|
||||||
1
dev/stripe.css
Normal file
1
dev/stripe.css
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -87,87 +87,43 @@ class DocumentationSearch {
|
||||||
// Given a list of hits returned by the API, will reformat them to be used in
|
// Given a list of hits returned by the API, will reformat them to be used in
|
||||||
// a Hogan template
|
// a Hogan template
|
||||||
formatHits(receivedHits) {
|
formatHits(receivedHits) {
|
||||||
// First, we move all the hierarchy object to the root
|
let hits = receivedHits.map((hit) => {
|
||||||
let hits = [];
|
hit._highlightResult = utils.mergeKeyWithParent(hit._highlightResult, 'hierarchy');
|
||||||
$.each(receivedHits, (index, item) => {
|
return utils.mergeKeyWithParent(hit, 'hierarchy');
|
||||||
let newItem = $.extend({}, item, item.hierarchy);
|
|
||||||
delete newItem.hierarchy;
|
|
||||||
hits.push(newItem);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let groupedHits = [];
|
|
||||||
// Add the first element as a main header
|
|
||||||
let firstElement = hits.shift();
|
|
||||||
firstElement.isCategoryHeader = true;
|
|
||||||
firstElement.isSubcategoryHeader = true;
|
|
||||||
// Add all elements that share both lvl0 and lvl1
|
|
||||||
$.each(hits, (index, item) => {
|
|
||||||
if !(item.lvl0 === firstElement.lvl0 && item.lvl1 === firstElement.lvl1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
groupedHits.push(item);
|
|
||||||
delete hits[index]
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get all remaining hits that share lvl0
|
|
||||||
let hitsThatShareLvl0 = [];
|
|
||||||
$.each(hits, (index, item) => {
|
|
||||||
if !(item.lvl0 === firstElement.lvl0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
hitsThatShareLvl0.push(item);
|
|
||||||
delete hits[index]
|
|
||||||
});
|
|
||||||
|
|
||||||
// Group the items sharing lvl0 together
|
|
||||||
$.each(hitsThatShareLvl0, (index, item) => {
|
|
||||||
});
|
|
||||||
|
|
||||||
// Flatten the lvl0 and add
|
|
||||||
// We take the first element of the array
|
|
||||||
// We take all other elements of the array that share lvl0 and lvl1 and put
|
|
||||||
// them after
|
|
||||||
// We then take all elements that share lvl0, order them by lvl1 and put
|
|
||||||
// them after
|
|
||||||
// We start over with the remaining of the array
|
|
||||||
|
|
||||||
return hits;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Given n hits, I'll take the first one in a separate list
|
|
||||||
// Then find (A) all the other hits that share both lvl0 and lvl1
|
|
||||||
// And (B) all the other hits that share only lvl0
|
|
||||||
// I'll group A and B into C. Set
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Group hits by category / subcategory
|
// Group hits by category / subcategory
|
||||||
console.info(hits);
|
var groupedHits = utils.groupBy(hits, 'lvl0');
|
||||||
var groupedHits = utils.groupBy(hits, 'category');
|
$.each(groupedHits, (level, collection) => {
|
||||||
console.info(groupedHits);
|
let groupedHitsByLvl1 = utils.groupBy(collection, 'lvl1');
|
||||||
groupedHits.each((list, category) => {
|
let flattenedHits = utils.flattenAndFlagFirst(groupedHitsByLvl1, 'isSubCategoryHeader');
|
||||||
var groupedHitsBySubCategory = groupBy(list, 'subcategory');
|
groupedHits[level] = flattenedHits;
|
||||||
var flattenedHits = utils.flattenObject(groupedHitsBySubCategory, 'isSubcategoryHeader');
|
|
||||||
groupedHits[category] = flattenedHits;
|
|
||||||
});
|
});
|
||||||
groupedHits = utils.flattenObject(groupedHits, 'isCategoryHeader');
|
groupedHits = utils.flattenAndFlagFirst(groupedHits, 'isCategoryHeader');
|
||||||
|
|
||||||
// Translate hits into smaller objects to be send to the template
|
// Translate hits into smaller objects to be send to the template
|
||||||
return groupedHits.map((hit) => {
|
return groupedHits.map((hit) => {
|
||||||
|
let url = hit.anchor ? `${hit.url}#${hit.anchor}` : hit.url;
|
||||||
|
let displayTitle = utils.compact([hit.lvl2, hit.lvl3, hit.lvl4, hit.lvl5, hit.lvl6]).join(' › ');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isCategoryHeader: hit.isCategoryHeader,
|
isCategoryHeader: hit.isCategoryHeader,
|
||||||
isSubcategoryHeader: hit.isSubcategoryHeader,
|
isSubcategoryHeader: hit.isSubcategoryHeader,
|
||||||
category: hit._highlightResult.category ? hit._highlightResult.category.value : hit.category,
|
category: this.getHighlightedValue(hit, 'lvl0'),
|
||||||
subcategory: hit._highlightResult.subcategory ? hit._highlightResult.subcategory.value : hit.category,
|
subcategory: this.getHighlightedValue(hit, 'lvl1'),
|
||||||
title: hit._highlightResult.display_title ? hit._highlightResult.display_title.value : hit.display_title,
|
title: displayTitle,
|
||||||
text: hit._snippetResult ? hit._snippetResult.text.value : hit.text,
|
text: hit.content,
|
||||||
url: hit.url
|
url: url
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHighlightedValue(object, key) {
|
||||||
|
let highlight = object._highlightResult[key];
|
||||||
|
console.info(highlight);
|
||||||
|
return highlight ? highlight.value : object[key];
|
||||||
|
}
|
||||||
|
|
||||||
getSuggestionTemplate() {
|
getSuggestionTemplate() {
|
||||||
const template = Hogan.compile(templates.suggestion);
|
const template = Hogan.compile(templates.suggestion);
|
||||||
return (suggestion) => {
|
return (suggestion) => {
|
||||||
|
|
|
||||||
186
src/lib/utils.js
186
src/lib/utils.js
|
|
@ -1,8 +1,7 @@
|
||||||
import $ from 'npm-zepto';
|
import $ from 'npm-zepto';
|
||||||
|
|
||||||
let utils = {
|
let utils = {
|
||||||
|
/*
|
||||||
/**
|
|
||||||
* Move the content of an object key one level higher.
|
* Move the content of an object key one level higher.
|
||||||
* eg.
|
* eg.
|
||||||
* {
|
* {
|
||||||
|
|
@ -18,42 +17,159 @@ let utils = {
|
||||||
* lvl0: 'Foo',
|
* lvl0: 'Foo',
|
||||||
* lvl1: 'Bar'
|
* lvl1: 'Bar'
|
||||||
* }
|
* }
|
||||||
* @param {Object} object Main object
|
* @param {Object} object Main object
|
||||||
* @param {String} key Main object key to move up
|
* @param {String} property Main object key to move up
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
* @throws Error when key is not an attribute of Object or is not an object itself
|
* @throws Error when key is not an attribute of Object or is not an object itself
|
||||||
*/
|
*/
|
||||||
mergeKeyWithParent(object, key) {
|
mergeKeyWithParent(object, property) {
|
||||||
if (object[key] === undefined) {
|
if (object[property] === undefined) {
|
||||||
throw new Error(`Object has no key ${key}`);
|
throw new Error(`[mergeKeyWithParent]: Object has no key ${property}`);
|
||||||
}
|
}
|
||||||
if (typeof object[key] !== 'object') {
|
if (typeof object[property] !== 'object') {
|
||||||
throw new Error(`Key ${key} is not an object`);
|
throw new Error(`[mergeKeyWithParent]: Key ${property} is not an object`);
|
||||||
}
|
}
|
||||||
let newObject = $.extend({}, object, object[key]);
|
let newObject = $.extend({}, object, object[property]);
|
||||||
delete newObject[key];
|
delete newObject[property];
|
||||||
return newObject;
|
return newObject;
|
||||||
}
|
},
|
||||||
// // Group all objects of `collection` by the key specified in `property`
|
/*
|
||||||
// groupBy(collection, property) {
|
* Group all objects of a collection by the value of the specified attribute
|
||||||
// let result = {};
|
* eg.
|
||||||
// $.each(collection, (index, item) => {
|
* groupBy([
|
||||||
// let key = item[property];
|
* {name: 'Tim', category: 'dev'},
|
||||||
// if (!result[key]) {
|
* {name: 'Vincent', category: 'dev'},
|
||||||
// result[key] = [];
|
* {name: 'Ben', category: 'sales'},
|
||||||
// }
|
* {name: 'Jeremy', category: 'sales'},
|
||||||
// result[key].push(item);
|
* {name: 'AlexS', category: 'dev'},
|
||||||
// });
|
* {name: 'AlexK', category: 'sales'}
|
||||||
// return result;
|
* ], 'category');
|
||||||
// },
|
* =>
|
||||||
// // Flatten all values into one array, marking the first element with
|
* {
|
||||||
// // `flagName`
|
* 'devs': [
|
||||||
// flattenObject(o, flagName) {
|
* {name: 'Tim', category: 'dev'},
|
||||||
// values(o).map((value) => {
|
* {name: 'Vincent', category: 'dev'},
|
||||||
// value[0][flagName] = true;
|
* {name: 'AlexS', category: 'dev'}
|
||||||
// });
|
* ],
|
||||||
// return flatten(values);
|
* 'sales': [
|
||||||
// }
|
* {name: 'Ben', category: 'sales'},
|
||||||
|
* {name: 'Jeremy', category: 'sales'},
|
||||||
|
* {name: 'AlexK', category: 'sales'}
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
* @param {array} collection Array of objects to group
|
||||||
|
* @param {String} property The attribute on which apply the grouping
|
||||||
|
* @return {array}
|
||||||
|
* @throws Error when one of the element does not have the specified property
|
||||||
|
*/
|
||||||
|
groupBy(collection, property) {
|
||||||
|
let newCollection = {};
|
||||||
|
$.each(collection, (index, item) => {
|
||||||
|
if (item[property] === undefined) {
|
||||||
|
throw new Error(`[groupBy]: Object has no key ${property}`);
|
||||||
|
}
|
||||||
|
let key = item[property];
|
||||||
|
if (!newCollection[key]) {
|
||||||
|
newCollection[key] = [];
|
||||||
|
}
|
||||||
|
newCollection[key].push(item);
|
||||||
|
});
|
||||||
|
return newCollection;
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
* Return an array of all the values of the specified object
|
||||||
|
* eg.
|
||||||
|
* values({
|
||||||
|
* foo: 42,
|
||||||
|
* bar: true,
|
||||||
|
* baz: 'yep'
|
||||||
|
* })
|
||||||
|
* =>
|
||||||
|
* [42, true, yep]
|
||||||
|
* @param {object} object Object to extract values from
|
||||||
|
* @return {array}
|
||||||
|
*/
|
||||||
|
values(object) {
|
||||||
|
return Object.keys(object).map(key => object[key]);
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
* Flattens an array
|
||||||
|
* eg.
|
||||||
|
* flatten([1, 2, [3, 4], [5, 6]])
|
||||||
|
* =>
|
||||||
|
* [1, 2, 3, 4, 5, 6]
|
||||||
|
* @param {array} array Array to flatten
|
||||||
|
* @return {array}
|
||||||
|
*/
|
||||||
|
flatten(array) {
|
||||||
|
let results = [];
|
||||||
|
array.forEach((value) => {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
results.push(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
value.forEach((subvalue) => {
|
||||||
|
results.push(subvalue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
* Flatten all values of an object into an array, marking each first element of
|
||||||
|
* each group with a specific flag
|
||||||
|
* eg.
|
||||||
|
* flattenAndFlagFirst({
|
||||||
|
* 'devs': [
|
||||||
|
* {name: 'Tim', category: 'dev'},
|
||||||
|
* {name: 'Vincent', category: 'dev'},
|
||||||
|
* {name: 'AlexS', category: 'dev'}
|
||||||
|
* ],
|
||||||
|
* 'sales': [
|
||||||
|
* {name: 'Ben', category: 'sales'},
|
||||||
|
* {name: 'Jeremy', category: 'sales'},
|
||||||
|
* {name: 'AlexK', category: 'sales'}
|
||||||
|
* ]
|
||||||
|
* , 'isTop');
|
||||||
|
* =>
|
||||||
|
* [
|
||||||
|
* {name: 'Tim', category: 'dev', isTop: true},
|
||||||
|
* {name: 'Vincent', category: 'dev', isTop: false},
|
||||||
|
* {name: 'AlexS', category: 'dev', isTop: false},
|
||||||
|
* {name: 'Ben', category: 'sales', isTop: true},
|
||||||
|
* {name: 'Jeremy', category: 'sales', isTop: false},
|
||||||
|
* {name: 'AlexK', category: 'sales', isTop: false}
|
||||||
|
* ]
|
||||||
|
* @param {object} object Object to flatten
|
||||||
|
* @param {string} flag Flag to set to true on first element of each group
|
||||||
|
* @return {array}
|
||||||
|
*/
|
||||||
|
flattenAndFlagFirst(object, flag) {
|
||||||
|
let values = this.values(object).map(value => {
|
||||||
|
value[0][flag] = true;
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
return this.flatten(values);
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
* Removes all empty strings, null, false and undefined elements array
|
||||||
|
* eg.
|
||||||
|
* compact([42, false, null, undefined, '', [], 'foo']);
|
||||||
|
* =>
|
||||||
|
* [42, [], 'foo']
|
||||||
|
* @param {array} array Array to compact
|
||||||
|
* @return {array}
|
||||||
|
*/
|
||||||
|
compact(array) {
|
||||||
|
let results = [];
|
||||||
|
array.forEach(value => {
|
||||||
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
results.push(value);
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default utils;
|
export default utils;
|
||||||
|
|
|
||||||
|
|
@ -89,4 +89,129 @@ describe('utils', () => {
|
||||||
}).toThrow(Error);
|
}).toThrow(Error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('groupBy', () => {
|
||||||
|
it('group by specified key', () => {
|
||||||
|
// Given
|
||||||
|
let input = [
|
||||||
|
{name: 'Tim', category: 'devs'},
|
||||||
|
{name: 'Vincent', category: 'devs'},
|
||||||
|
{name: 'Ben', category: 'sales'},
|
||||||
|
{name: 'Jeremy', category: 'sales'},
|
||||||
|
{name: 'AlexS', category: 'devs'},
|
||||||
|
{name: 'AlexK', category: 'sales'}
|
||||||
|
];
|
||||||
|
|
||||||
|
// When
|
||||||
|
let actual = utils.groupBy(input, 'category');
|
||||||
|
|
||||||
|
// Expect
|
||||||
|
expect(actual).toEqual({
|
||||||
|
devs: [
|
||||||
|
{name: 'Tim', category: 'devs'},
|
||||||
|
{name: 'Vincent', category: 'devs'},
|
||||||
|
{name: 'AlexS', category: 'devs'}
|
||||||
|
],
|
||||||
|
sales: [
|
||||||
|
{name: 'Ben', category: 'sales'},
|
||||||
|
{name: 'Jeremy', category: 'sales'},
|
||||||
|
{name: 'AlexK', category: 'sales'}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('throw an error if key does not exist', () => {
|
||||||
|
// Given
|
||||||
|
let input = [
|
||||||
|
{name: 'Tim'},
|
||||||
|
{name: 'Vincent'},
|
||||||
|
{name: 'Ben'},
|
||||||
|
{name: 'Jeremy'},
|
||||||
|
{name: 'AlexS'},
|
||||||
|
{name: 'AlexK'}
|
||||||
|
];
|
||||||
|
|
||||||
|
// When
|
||||||
|
expect(() => {
|
||||||
|
utils.groupBy(input, 'category');
|
||||||
|
}).toThrow(Error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('values', () => {
|
||||||
|
it('should extract all values', () => {
|
||||||
|
// Given
|
||||||
|
let input = {
|
||||||
|
foo: 42,
|
||||||
|
bar: true,
|
||||||
|
baz: 'yep'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Given
|
||||||
|
let actual = utils.values(input);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(actual.length).toEqual(3);
|
||||||
|
expect(actual).toInclude(42);
|
||||||
|
expect(actual).toInclude(true);
|
||||||
|
expect(actual).toInclude('yep');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('flatten', () => {
|
||||||
|
// flatten values
|
||||||
|
it('should flatten array on level deep', () => {
|
||||||
|
// Given
|
||||||
|
let input = [1, 2, [3, 4], [5, 6]];
|
||||||
|
|
||||||
|
// Given
|
||||||
|
let actual = utils.flatten(input);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(actual).toEqual([1, 2, 3, 4, 5, 6]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('flattenAndFlagFirst', () => {
|
||||||
|
it('should flatten all values', () => {
|
||||||
|
// Given
|
||||||
|
let input = {
|
||||||
|
'devs': [
|
||||||
|
{name: 'Tim', category: 'dev'},
|
||||||
|
{name: 'Vincent', category: 'dev'},
|
||||||
|
{name: 'AlexS', category: 'dev'}
|
||||||
|
],
|
||||||
|
'sales': [
|
||||||
|
{name: 'Ben', category: 'sales'},
|
||||||
|
{name: 'Jeremy', category: 'sales'},
|
||||||
|
{name: 'AlexK', category: 'sales'}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// When
|
||||||
|
let actual = utils.flattenAndFlagFirst(input, 'isTop');
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(actual).toEqual([
|
||||||
|
{name: 'Tim', category: 'dev', isTop: true},
|
||||||
|
{name: 'Vincent', category: 'dev'},
|
||||||
|
{name: 'AlexS', category: 'dev'},
|
||||||
|
{name: 'Ben', category: 'sales', isTop: true},
|
||||||
|
{name: 'Jeremy', category: 'sales'},
|
||||||
|
{name: 'AlexK', category: 'sales'}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('compact', () => {
|
||||||
|
it('should clear all falsy elements from the array', () => {
|
||||||
|
// Given
|
||||||
|
let input = [42, false, null, undefined, '', [], 'foo'];
|
||||||
|
|
||||||
|
// When
|
||||||
|
let actual = utils.compact(input);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(actual).toEqual([42, [], 'foo']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue