Last active
January 13, 2017 19:54
-
-
Save caseyWebb/5b719973f7df3e9ae94705b521d86264 to your computer and use it in GitHub Desktop.
Link-List Refactor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
let _; const { each, map, some, every } = _ = require('lodash') | |
const ko = require('knockout') | |
const $ = require('jquery') | |
const Query = require('ko-querystring').default | |
module.exports = class LinkList { | |
constructor({ | |
sections, | |
select2 = false, | |
topComponent, | |
bottomComponent | |
}) { | |
this.query = new Query({ | |
search: '', | |
finder: [] | |
}) | |
this.subs = [ | |
this.query.search.subscribe(() => $('html, body').animate({ scrollTop: 0 }, 'fast')) | |
] | |
this.select2 = select2 | |
if (topComponent) { | |
this.topComponent = true | |
ko.components.register('top-component', topComponent) | |
} | |
if (bottomComponent) { | |
this.bottomComponent = true | |
ko.components.register('bottom-component', bottomComponent) | |
} | |
this.sections = _.map(sections, (s) => new Section(s, this.query.search)) | |
this.allHidden = ko.pureComputed(() => !_.some(this.sections, (s) => s.visible())) | |
} | |
get navItems() { | |
return map(this.sections, 'text') | |
} | |
get keywords() { | |
return _(this.sections) | |
.flatMap((s) => s.links) | |
.flatMap((l) => l.keywords) | |
.value() | |
} | |
dispose() { | |
if (this.topComponent) { | |
ko.components.unregister('top-component') | |
} | |
if (this.bottomComponent) { | |
ko.components.unregister('bottom-component') | |
} | |
each(this.subs, (s) => s.dispose()) | |
} | |
} | |
class Section { | |
constructor({ | |
text, | |
links | |
}, search) { | |
this.text = text | |
this.id = this.text.replace(/\s+/i, '-') | |
this.links = map(links, (l) => new Link(l, search, getKeywords(this.text.split(/\W+/)))) | |
this.visible = ko.pureComputed(() => some(this.links, (l) => l.visible())) | |
} | |
} | |
class Link { | |
constructor({ | |
text, | |
url, | |
external = false, | |
keywords = [], | |
help = false | |
}, search, sectionKeywords) { | |
this.text = text | |
this.url = url | |
this.external = external | |
this.help = help | |
this.keywords = getKeywords(keywords.concat(sectionKeywords).concat(this.text.split(/\W+/))) | |
this.visible = ko.pureComputed(() => | |
every(search().toLowerCase().split(/\W+/), (token) => | |
_.some(this.keywords, (k) => | |
_.includes(k, token)))) | |
} | |
} | |
function getKeywords(words) { | |
return _(words) | |
.uniq() | |
.without('a', 'an', 'and', 'all', 'are', 'be', 'by', 'do', 'ed', 'for', 'if', 'in', 'me', 'of', 'or', 'to', 'you', 'your') | |
.invokeMap('toLowerCase') | |
.value() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const API = ApiBase + 'InstructorUsers/GetCustomFieldNames' | |
const ko = require('knockout') | |
const $ = require('jquery') | |
const _ = require('lodash') | |
const breadcrumbs = require('components/breadcrumbs') | |
const QueryCache = require('utils/query-cache') | |
const api = require('api') | |
const find = (w1, w2) => typeof w2 === 'string' && typeof w1 === 'string' | |
? w1.toLowerCase().indexOf(w2.toLowerCase()) !== -1 | |
: false | |
const addFields = (words, userCustomFields) => { | |
// Change the Learner-Custom-Fields to their appropriate names | |
if (words.indexOf('Learner-Custom-Fields') !== -1) { | |
words.splice(words.indexOf('Learner-Custom-Fields'), 1) | |
words = words.concat(userCustomFields) | |
} | |
return words | |
} | |
module.exports = class { | |
constructor(params) { | |
this.ready = ko.observable(false) | |
const cache = QueryCache.exists(API) ? QueryCache.getCache(API) : new QueryCache(API) | |
new Promise((resolve) => cache.hasQuery({}) | |
? resolve(cache.getQuery({}).metadata) | |
: api.get(API).then((response) => { | |
cache.setQuery({ query: {}, response, getMetadata: (r) => r, getResources: (r) => r }) | |
resolve(response) | |
})).then((res) => { | |
const userCustomFields = res | |
const pages = params.pages.list | |
this.subs = [] | |
this.query = params.pages.ctx.$parent ? params.pages.ctx.$parent.query : params.pages.ctx.query | |
this.searchByFields = params.pages.fieldNames || false // Used as boolean | |
if (this.searchByFields) this.types = this.searchByFields | |
this.select2 = params.pages.select2 === true | |
this.showAll = params.pages.showAll || this.searchByFields | |
this.query.setDefaults({ | |
search: '', | |
finder: [] | |
}) | |
this.searchText = this.query.get('search') | |
this.subs.push(this.searchText.subscribe(() => $('html, body').animate({ scrollTop: 0 }, 'fast'))) | |
if (params.pages.bcs) breadcrumbs.set(params.pages.bcs) | |
if (params.pages.topComponent) { | |
this.topComponent = params.pages.topComponent | |
if (!ko.components.isRegistered('top-component')) { | |
ko.components.register('top-component', this.topComponent) | |
} | |
} | |
if (params.pages.bottomComponent) { | |
this.bottomComponent = params.pages.bottomComponent | |
if (!ko.components.isRegistered('top-component')) { | |
ko.components.register('bottom-component', this.bottomComponent) | |
} | |
} | |
// Hide 'Background Tasks' on cloud sites except when logged in as 'userid=0' (administrator) | |
if (document.location.hostname.toLowerCase().indexOf('.universitysite.com') > -1 | |
&& window.globals.CurrentUser.ID() !== 1) | |
_.each(pages, (page) => _.remove(page.links, (link) => link.url == 'background-tasks')) | |
this.navItems = _.map(pages, (p) => p.id ? { text: p.text, anchor: p.id } : p.text) | |
this.numTerms = ko.pureComputed(() => this.query.get('finder')() ? this.query.get('finder')().length : 0) | |
this.finderEmpty = ko.pureComputed(() => !this.query.get('finder')() || this.numTerms() === 0) | |
this.finderHasAll = ko.pureComputed(() => this.query.get('finder')() && _.find(this.query.get('finder')(), (s) => s.id === 'All')) | |
this.searchEmpty = ko.pureComputed(() => !this.searchText() || this.searchText() === '') | |
this.sections = _.map(pages, (page) => { | |
page.links = _.map(page.links, (link) => { | |
link.showAll = ko.observable(false) | |
link.fields = [] | |
if (!link.keywords) link.keywords = [] | |
link.keywords.push({ text: 'Heading', shouldShow: false, words: [page.text] }) | |
_.each(link.keywords, (k) => { | |
if (!k.text) k = { text: 'Keyword', words: [k] } | |
Array.prototype.push.apply(link.fields, _.map(addFields(k.words, userCustomFields), (w) => { | |
k.shouldShow === false || (k.shouldShow = true) | |
return { | |
text: `${w} (${k.text})`, | |
help: k.help, | |
shouldShow: k.shouldShow, | |
field: w, | |
visible: ko.pureComputed(() => this.query.get('finder')() && | |
this.searchByFields | |
? this.numTerms() > 0 && _.find(this.query.get('finder')(), (s) => | |
s.id.indexOf('-') === -1 ? find(w, s.id) : w === s.id) | |
: !this.searchEmpty() && find(w, this.searchText())), | |
showAll: link.showAll | |
}})) | |
}) | |
// how many fields are visible | |
link.visibleFields = ko.pureComputed(() => _.filter(link.fields, (f) => f.visible())) | |
// How many unique fields are visible | |
link.uniqFields = ko.pureComputed(() => { | |
const arr = [] | |
_.each(link.visibleFields(), (f) => | |
!_.find(arr, (a) => a.field === f.field) && arr.push(f)) | |
return arr | |
}) | |
link.matchSearch = ko.pureComputed(() => !this.searchEmpty() && find(link.text, this.query.get('search')())) | |
link.matchFinder = ko.pureComputed(() => !this.finderEmpty() && link.uniqFields().length >= this.numTerms()) | |
link.visible = ko.pureComputed(() => | |
this.searchByFields | |
? (this.searchEmpty() && this.finderEmpty()) | |
|| (this.finderEmpty() && link.matchSearch()) | |
|| (this.searchEmpty() && link.matchFinder()) | |
|| (link.matchFinder() && link.matchSearch()) | |
|| this.finderHasAll() | |
: this.searchEmpty() || link.visibleFields().length > 0 || link.matchSearch()) | |
link.words = [] | |
_.each(link.fields, (f) => { | |
Array.prototype.push.apply(link.words, f.text.split(' ')) | |
}) | |
return link | |
}) | |
page.visible = ko.pureComputed(() => _.findIndex(page.links, (l) => l.visible()) >= 0) | |
return page | |
}) | |
this.visibleSections = ko.pureComputed(() => _.filter(this.sections, (s) => s.visible()).length) | |
this.keywords = [] | |
_.each(this.sections, (p) => _.each(p.links, (l) => | |
Array.prototype.push.apply(this.keywords, addFields(l.words, userCustomFields)))) | |
this.keywords = _(this.keywords).sortBy().uniq() | |
.filter((w) => ((w.charCodeAt(0) > 96 && w.charCodeAt(0) < 123) || (w.charCodeAt(0) > 64 && w.charCodeAt(0) < 91)) | |
&& w.search('<') === -1) | |
.map((w) => w.replace('.', '')) | |
.reject((w) => _.includes(['a', 'an', 'and', 'all', 'are', 'be', 'by', 'do', 'ed', 'for', 'if', 'in', 'me', 'of', 'or', 'to', 'you', 'your'], w)) | |
.map((w) => {return { | |
id: w, | |
text: w | |
}}).toArray().value() | |
this.ready(true) | |
}) | |
} | |
dispose() { | |
if (ko.components.isRegistered('top-component')) ko.components.unregister('top-component') | |
if (ko.components.isRegistered('bottom-component')) ko.components.unregister('bottom-component') | |
_.each(this.subs, (s) => s.dispose()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment