mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-02-22 04:30:33 +09:00
135 lines
4.1 KiB
JavaScript
135 lines
4.1 KiB
JavaScript
import { camelize, normalize, regexpForQuery, uniqueValues } from "lib/autocomplete/utils"
|
|
|
|
export default class AutocompletableCollection {
|
|
#autocompletables
|
|
#index
|
|
|
|
constructor(autocompletables = [], options = {}) {
|
|
this.#index = new Map()
|
|
this.#autocompletables = new Array()
|
|
|
|
Array.from(autocompletables).forEach((autocompletable) => {
|
|
this.#index.set(this.#uniqueAutocompleteableKey(autocompletable), autocompletable)
|
|
})
|
|
|
|
this.#index.forEach(autocompletable => {
|
|
this.#autocompletables.push(autocompletable)
|
|
})
|
|
|
|
if (options.sort !== false) {
|
|
this.#autocompletables.sort(this.#compareAutocompletables)
|
|
}
|
|
}
|
|
|
|
get(value) {
|
|
return this.#index.get(value.toString())
|
|
}
|
|
|
|
has(value) {
|
|
return this.#index.has(value.toString())
|
|
}
|
|
|
|
add(autocompletables = [], collectionOptions) {
|
|
return new this.constructor(this.#autocompletables.concat(autocompletables), collectionOptions)
|
|
}
|
|
|
|
getValues() {
|
|
return this.#autocompletables.map(autocompletable => autocompletable.value)
|
|
}
|
|
|
|
withValues(values = [], collectionOptions) {
|
|
const autocompletables = values.map((value) => this.get(value)).filter(Boolean)
|
|
return new this.constructor(autocompletables, collectionOptions)
|
|
}
|
|
|
|
withoutValues(values = [], collectionOptions) {
|
|
const autocompletables = []
|
|
this.#index.forEach(function(autocompletable, value) {
|
|
const allGroupMembersAreAdded = autocompletable.type == "group" && autocompletable.value.split(",").every(id => values.includes(id))
|
|
|
|
if (!values.includes(value) && !allGroupMembersAreAdded) {
|
|
return autocompletables.push(autocompletable)
|
|
}
|
|
})
|
|
return new this.constructor(autocompletables, collectionOptions)
|
|
}
|
|
|
|
filter(callback, collectionOptions) {
|
|
if (!callback) { return this }
|
|
|
|
const autocompletables = []
|
|
this.#index.forEach(function(autocompletable, value) {
|
|
if (callback(autocompletable)) {
|
|
return autocompletables.push(autocompletable)
|
|
}
|
|
})
|
|
|
|
return new this.constructor(autocompletables, collectionOptions)
|
|
}
|
|
|
|
matchingQuery(query) {
|
|
if (!query) { return this }
|
|
|
|
return new this.constructor(
|
|
this.#matchAutocompletablesByNameOrDescription(this.#autocompletables, query),
|
|
{ sort: false }
|
|
)
|
|
}
|
|
|
|
toArray() {
|
|
return this.#autocompletables.slice(0)
|
|
}
|
|
|
|
toJSON() {
|
|
return this.toArray()
|
|
}
|
|
|
|
isEqualTo(collection) {
|
|
if (!collection || (this.#autocompletables.length !== collection.length)) {
|
|
return false
|
|
}
|
|
|
|
return JSON.stringify(this) === JSON.stringify(collection)
|
|
}
|
|
|
|
#compareAutocompletables(autocompletable, otherAutocompletable) {
|
|
return autocompletable.name.localeCompare(otherAutocompletable.name)
|
|
}
|
|
|
|
#matchAutocompletablesByNameOrDescription(autocompletables, query) {
|
|
return uniqueValues([].concat(
|
|
this.#matchAutocompletablesByNameAtHead(autocompletables, query),
|
|
this.#matchAutocompletablesByRestOfName(autocompletables, query),
|
|
this.#matchAutocompletablesByRestOfDescription(autocompletables, query))
|
|
)
|
|
}
|
|
|
|
#matchAutocompletablesByNameAtHead(autocompletables, query) {
|
|
return this.#matchAutocompletablesByRegExp(autocompletables, regexpForQuery(query, "^"))
|
|
}
|
|
|
|
#matchAutocompletablesByRestOfName(autocompletables, query) {
|
|
return this.#matchAutocompletablesByRegExp(autocompletables, regexpForQuery(query, "\\s"))
|
|
}
|
|
|
|
#matchAutocompletablesByRestOfDescription(autocompletables, query) {
|
|
return this.#matchAutocompletablesByRegExp(autocompletables, regexpForQuery("", query), "description")
|
|
}
|
|
|
|
#matchAutocompletablesByRegExp(autocompletables, regexp, propertyName = "name") {
|
|
return autocompletables.filter(autocompletable => {
|
|
const normalizedPropertyName = `normalized${camelize(propertyName)}`
|
|
const property = autocompletable[propertyName]
|
|
|
|
if (property) {
|
|
if (!autocompletable[normalizedPropertyName]) autocompletable[normalizedPropertyName] = normalize(property)
|
|
return regexp.test(autocompletable[normalizedPropertyName])
|
|
}
|
|
})
|
|
}
|
|
|
|
#uniqueAutocompleteableKey(autocompletable) {
|
|
return autocompletable.value.toString()
|
|
}
|
|
}
|