Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
aa827b9
Add tests for page and page_size
May 29, 2017
134988c
Change ' ' to '-' instead of '+'
May 29, 2017
c0607b7
Don't generate /q when it's not necessary
May 29, 2017
d679796
Allow page even when page_size is not specified
May 29, 2017
94f2033
Revert "Don't generate /q when it's not necessary"
May 29, 2017
e44fb84
Add option to disable reference keys
May 29, 2017
24afb53
Use ':' to connect navigation name and navigation value of value refi…
May 30, 2017
3d7d52a
Parse query and value refinements from URL without reference keys
May 30, 2017
25723f9
parse pageSize and page from URL
May 30, 2017
c8f41c5
Add test for URL with suffix
May 30, 2017
87ef216
Extract URL Beautifier interfaces
jmbtutor May 30, 2017
13691d0
Separate generator and parser into separate modules
May 31, 2017
9b68bb0
Parse simple navigation url and return a query
May 31, 2017
333816f
handle case where no navigation mapping exits
May 31, 2017
ce6137c
handle case where navigation url has more than one part
May 31, 2017
ddcece8
Parse navigation url with encoded characters
May 31, 2017
7e91190
Build navigation url with encoded characters
May 31, 2017
7ac3de7
Throw error when passing unmapped name to generator
Jun 1, 2017
3b7493f
Generate URL for simple details page
Jun 1, 2017
82b3c34
Add refinements to the generated details URL
Jun 1, 2017
4160d21
Replace '-' with ' ' when parsing navigation url
Jun 1, 2017
e989141
Finish detail url generator
Jun 1, 2017
5cc4d2c
Parse detail page url without reference keys
Jun 1, 2017
5d9a161
Finish detail url parser
Jun 1, 2017
751ff44
test compatibility for detail url beautifier
Jun 1, 2017
75b87ee
Clean up url-beautifier tests
Jun 2, 2017
933fa08
Incomplete
Jun 2, 2017
806012a
Wrapper function
jmbtutor Jun 2, 2017
2f6b854
Make sandbox work
jmbtutor Jun 2, 2017
3d92713
Add compatibility tests
Jun 6, 2017
1177fac
Make parser accept uri object
Jun 6, 2017
7b0f697
Improve code formating
Jun 7, 2017
c9f09de
Change detail.refinements to non-nullable
Jun 7, 2017
664a448
Apply review changes (#200)
effervescentia Jun 8, 2017
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
227 changes: 0 additions & 227 deletions src/utils/url-beautifier.ts

This file was deleted.

112 changes: 112 additions & 0 deletions src/utils/url-beautifier/detail-url-beautifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Beautifier, BeautifierConfig, Detail } from './interfaces';
import { SelectedValueRefinement } from 'groupby-api';

export class DetailUrlGenerator {
Copy link
Contributor

Choose a reason for hiding this comment

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

make an interface

config: BeautifierConfig;

constructor({ config }: Beautifier) {
this.config = config;
}

build(detail: Detail): string {
let paths = [detail.productTitle];

if (detail.refinements.length !== 0) {
if (this.config.useReferenceKeys) {
let referenceKeys = '';
const refinementsToKeys = this.config.refinementMapping.reduce((map, mapping) => {
const key = Object.keys(mapping)[0];
map[mapping[key]] = key;
return map;
}, {});

detail.refinements.sort(DetailUrlGenerator.refinementsComparator)
.forEach((refinement) => {
if (!(refinement.navigationName in refinementsToKeys)) {
throw new Error(`no mapping found for navigation '${refinement.navigationName}'`);
}

paths.push(refinement.value);
referenceKeys += refinementsToKeys[refinement.navigationName];
});

paths.push(referenceKeys);
} else {
detail.refinements.forEach(({ value, navigationName }) => paths.push(value, navigationName));
}
}

paths.push(detail.productId);
return `/${paths.map((path) => encodeURIComponent(path.replace(/\s/g, '-'))).join('/')}`;
}

static refinementsComparator(refinement1: SelectedValueRefinement, refinement2: SelectedValueRefinement): number {
let comparison = refinement1.navigationName.localeCompare(refinement2.navigationName);
if (comparison === 0) {
comparison = refinement1.value.localeCompare(refinement2.value);
}
return comparison;
}
}

export class DetailUrlParser {
Copy link
Contributor

Choose a reason for hiding this comment

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

make an interface

config: BeautifierConfig;

constructor({ config }: Beautifier) {
this.config = config;
}

parse(url: { path: string, query: string}): Detail {
const paths = url.path.split('/').filter((val) => val).map((val) => decodeURIComponent(val).replace(/-/g, ' '));

if (paths.length < 2) {
throw new Error('path has less than two parts');
}

const name = paths.shift();
const id = paths.pop();

const refinements = [];

if (paths.length !== 0) {
if (!this.config.useReferenceKeys) {
if (paths.length % 2 !== 0) {
throw new Error('path has an odd number of parts');
}

while (paths.length !== 0) {
const value = paths.shift();
const navigationName = paths.shift();
refinements.push({ navigationName, value, type: 'Value' });
}
} else {
if (paths.length < 2) {
Copy link
Contributor

Choose a reason for hiding this comment

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

couldn't it have multiple sets of refinements?

throw new Error('path has wrong number of parts');
Copy link

Choose a reason for hiding this comment

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

I would say "path has too few parts" or "path has fewer than two parts"

Copy link
Author

Choose a reason for hiding this comment

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

I don't think it needs to be changed because the paths in this context excluded productId and productTiltle, so the actual path length is longer than 2.

}

const referenceKeys = paths.pop().split('');
const keysToRefinements = this.config.refinementMapping.reduce((map, mapping) => {
const key = Object.keys(mapping)[0];
map[key] = mapping[key];
return map;
}, {});

if (paths.length !== referenceKeys.length) {
throw new Error('token reference is invalid');
}

paths.forEach((value) => refinements.push({
value,
navigationName: keysToRefinements[referenceKeys.shift()],
type: 'Value'
}));
}
}

return {
productTitle: name,
productId: id,
refinements
};
}
}
17 changes: 17 additions & 0 deletions src/utils/url-beautifier/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DetailUrlGenerator, DetailUrlParser } from './detail-url-beautifier';
import { BeautifierConfig, Detail } from './interfaces';
import { NavigationUrlGenerator, NavigationUrlParser } from './navigation-url-beautifier';
import { QueryUrlGenerator, QueryUrlParser } from './query-url-beautifier';
import { UrlBeautifier } from './url-beautifier';

export {
BeautifierConfig,
Detail,
DetailUrlGenerator,
DetailUrlParser,
NavigationUrlGenerator,
NavigationUrlParser,
QueryUrlGenerator,
QueryUrlParser,
UrlBeautifier
};
34 changes: 34 additions & 0 deletions src/utils/url-beautifier/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { SearchandiserConfig } from '../../searchandiser';
import { SelectedValueRefinement } from 'groupby-api';

export interface Beautifier {
config: BeautifierConfig;
searchandiserConfig: SearchandiserConfig;
parse(rawUrl: string): any;
build(query: any): string;
}

export interface BeautifierConfig {
refinementMapping?: any[];
params?: {
page?: string;
pageSize?: string;
refinements?: string;
sort?: string;
};
queryToken?: string;
suffix?: string;
useReferenceKeys?: boolean;
navigations?: any;
routes: {
query: string,
detail: string,
navigation: string
};
}

export interface Detail {
productTitle: string;
productId: string;
refinements: SelectedValueRefinement[];
}
Loading