1 Commits

Author SHA1 Message Date
9684309e6a chore: monorepo 2018-08-30 19:03:14 -07:00
30 changed files with 125 additions and 7147 deletions

6
.gitignore vendored
View File

@@ -7,8 +7,6 @@ yarn-error.log
.env
coverage
.nyc_output
.firebase
.firebaserc
coverage.lcov
dist/
db.json
/lib
db.json

View File

@@ -1,3 +0,0 @@
### Authors
- joe fleming ([w33ble](https://github.com/w33ble))

View File

@@ -1,29 +0,0 @@
### Changelog
#### [v1.1.0](https://git.w33ble.com/w33ble/strain-tools/compare/v1.0.2...v1.1.0) (18 September 2018)
- feat: basic routing and fav nav [`3b39345`](https://git.w33ble.com/w33ble/strain-tools/commit/3b39345fa66ac4748a400e9e80e032ec9ae9697b)
- feat: show favorite strain cards [`85efbd8`](https://git.w33ble.com/w33ble/strain-tools/commit/85efbd84d1704c55a3eefae7fa2d36e7fd7f3cc2)
- fix: weird bug in StrainList [`2c60ec4`](https://git.w33ble.com/w33ble/strain-tools/commit/2c60ec4afc16f81fd6b610443091d26d278d3f81)
#### [v1.0.2](https://git.w33ble.com/w33ble/strain-tools/compare/v1.0.1...v1.0.2) (13 September 2018)
#### [v1.0.1](https://git.w33ble.com/w33ble/strain-tools/compare/v1.0.0...v1.0.1) (13 September 2018)
- fix: correct localstorage fallback [`d5b0cd0`](https://git.w33ble.com/w33ble/strain-tools/commit/d5b0cd07307dbf06d8d4530803a00c2b2ab8c4c5)
- docs: update readme with usable scripts [`5bdd35b`](https://git.w33ble.com/w33ble/strain-tools/commit/5bdd35b74b417706c76bd50d7162567b60dbdcb2)
- fix: scrape strains alphabetically [`fa2db8d`](https://git.w33ble.com/w33ble/strain-tools/commit/fa2db8d4304b0b0d91221b4ef942daa74ab3df94)
#### v1.0.0 (9 September 2018)
- fix: assign key to strain cards [`e3e95e7`](https://git.w33ble.com/w33ble/strain-tools/commit/e3e95e7c2b390ca52633e84604cf6a4a9b239d54)
- fix: remove listener on form unmount [`4591a47`](https://git.w33ble.com/w33ble/strain-tools/commit/4591a47dbaa62cbd330bbc9b96ace2be1ace8bd6)
- feat: add fav/unfav control [`50a3b1d`](https://git.w33ble.com/w33ble/strain-tools/commit/50a3b1db92a64fcd7e10e35ba045a3970a1440ba)
- feat: adjust card tag label by screen size [`5665bde`](https://git.w33ble.com/w33ble/strain-tools/commit/5665bdeaa99bcbf4fc5a9d13d98803b17a42404b)
- feat: sort by adjusted rating [`712c5c0`](https://git.w33ble.com/w33ble/strain-tools/commit/712c5c095c52269d7ffbd7f763cdf325b11369a4)
- feat: show errors, sort tags [`943c091`](https://git.w33ble.com/w33ble/strain-tools/commit/943c0917c71db1612aefd9f2fc8bde098000364c)
- feat: functional search on site [`d3b2110`](https://git.w33ble.com/w33ble/strain-tools/commit/d3b21103eb5227101f581fcc853714bc78ea9950)
- feat: even more site functionality [`9a1f2f9`](https://git.w33ble.com/w33ble/strain-tools/commit/9a1f2f9785e36bd2de2a3a1fbf46bbc9cfdb90d3)
- feat: add tags to scraper output [`804fac1`](https://git.w33ble.com/w33ble/strain-tools/commit/804fac1afb68dc52f482cbfa393856b14b64400a)
- feat: mocked up search form on site [`22a95c3`](https://git.w33ble.com/w33ble/strain-tools/commit/22a95c3fe827ec0651c44164f58950dcc283354b)
- feat: simple site build and dev server [`699a03c`](https://git.w33ble.com/w33ble/strain-tools/commit/699a03c7c06da011b64bdc358287f5d653c96c92)
- feat: add a search site package [`37dcabd`](https://git.w33ble.com/w33ble/strain-tools/commit/37dcabde5e20a6ecea803f40798ae43c72e3afe8)
- feat: working scraper [`cc5e15d`](https://git.w33ble.com/w33ble/strain-tools/commit/cc5e15dbb11f388ba260da6c196fe6827e947d3c)
- initial commit [`c81b30b`](https://git.w33ble.com/w33ble/strain-tools/commit/c81b30be896009b48e66005007f88e55fb159c9c)

View File

@@ -1,8 +1,10 @@
# strain-tools
# strain-scraper
![license](https://img.shields.io/badge/license-MIT-blue.svg)
scrapes strain info, stores for later reference.
Monorepo for cannabis strain tools. For repos, check in `packages`.
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/w33ble/strain-scraper/master/LICENSE)
[![npm](https://img.shields.io/npm/v/strain-scraper.svg)](https://www.npmjs.com/package/strain-scraper)
[![Project Status](https://img.shields.io/badge/status-experimental-orange.svg)](https://nodejs.org/api/documentation.html#documentation_stability_index)
#### License

View File

@@ -1,16 +1,14 @@
{
"name": "strain-tools",
"version": "1.1.0",
"version": "0.0.0",
"description": "strain tools",
"main": "index",
"module": "index.mjs",
"private": true,
"scripts": {
"lint": "eslint \"packages/*/*.{js,mjs,vue}\" \"packages/*/src/**/*.{js,mjs,vue}\"",
"lint": "eslint \"*.{js,mjs}\" \"src/**/*.{js,mjs}\"",
"precommit": "lint-staged",
"prepush": "npm run lint",
"sync-versions": "node -r esm scripts/version-sync.mjs",
"version": "npm run sync-versions && auto-changelog -p && auto-authors && git add CHANGELOG.md AUTHORS.md packages",
"version": "auto-changelog -p && auto-authors && git add CHANGELOG.md AUTHORS.md",
"start": "node .",
"dev": "nodemon --ignore db.json ."
},
@@ -33,10 +31,10 @@
"commitLimit": false
},
"lint-staged": {
"*.{js,mjs,vue}": [
"*.{js,mjs}": [
"eslint --fix"
],
"*.{js,mjs,vue,json,css}": [
"*.{js,mjs,json,css}": [
"prettier --write"
]
},

View File

@@ -1,10 +0,0 @@
# leafly-scraper
Scrapes strain info, stores for later reference.
Clone repo and run the command. Resulting data can be found in `db.json`.
```
yarn install
yarn start
```

View File

@@ -1,7 +1,6 @@
{
"name": "scraper",
"version": "1.1.0",
"private": true,
"name": "leafly-scraper",
"version": "0.0.0",
"description": "scrapes strain info, stores for later reference",
"main": "index",
"module": "index.mjs",
@@ -19,6 +18,14 @@
],
"author": "joe fleming (https://github.com/w33ble)",
"license": "MIT",
"lint-staged": {
"*.{js,mjs}": [
"eslint --fix"
],
"*.{js,mjs,json,css}": [
"prettier --write"
]
},
"prettier": {
"printWidth": 100,
"singleQuote": true,
@@ -29,7 +36,7 @@
},
"dependencies": {
"axios": "^0.18.0",
"esm": "^3.0.82",
"esm": "^3.0.17",
"lodash": "^4.17.10",
"lowdb": "^1.0.0"
},

View File

@@ -8,14 +8,12 @@ const adapter = new FileAsync('db.json');
const xhr = axios.create({
headers: {
Accept: 'application/json, text/plain, */*',
Referer: 'https://www.leafly.com/explore/sort-alpha',
Referer: 'https://www.leafly.com/explore',
},
});
const pSeries = tasks => tasks.reduce((c, task) => c.then(task), Promise.resolve());
const getPage = async num => {
const url = `https://www.leafly.com/explore/page-${num}/sort-alpha`;
const url = `https://www.leafly.com/explore/page-${num}`;
const response = await xhr.get(url, {
responseType: 'json',
});
@@ -47,63 +45,28 @@ export default async function scrapeLeafly(startFrom = 1, endAt = Infinity) {
let finished = false;
const db = await low(adapter);
async function writeTag(type, tag) {
const res = await db
.get(type)
.indexOf(tag)
.value();
if (res < 0) {
await db
.get(type)
.push(tag)
.write();
}
}
async function writeTags(type, tags) {
await pSeries(tags.map(tag => () => writeTag(type, tag)));
}
async function writeDoc(strain) {
// check for value
const doc = db
.get('strains')
.filter({ id: strain.id })
.first()
.value();
if (!doc) {
console.log(`Adding ${strain.id}, ${strain.name}`);
await db
.get('strains')
.push(strain)
.write();
await writeTags('effects', strain.effects);
await writeTags('negative_effects', strain.negative_effects);
await writeTags('uses', strain.uses);
await writeTags('conditions', strain.conditions);
await writeTags('flavors', strain.flavors);
}
}
await db
.defaults({
strains: [],
effects: [],
negative_effects: [],
uses: [],
conditions: [],
flavors: [],
})
.write();
await db.defaults({ strains: [] }).write();
while (!finished) {
console.log(`Fetching page ${pageNum}`);
const data = await getPage(pageNum);
await pSeries(data.strains.map(strain => () => writeDoc(strain)));
data.strains.forEach(async strain => {
// check for value
const doc = db
.get('strains')
.filter({ id: strain.id })
.first()
.value();
if (!doc) {
console.log(`Adding ${strain.id}, ${strain.name}`);
await db
.get('strains')
.push(strain)
.write();
}
});
if (pageNum >= endAt || !data.strains.length || data.page.isLastPage) finished = true;
pageNum += 1;

View File

@@ -1,23 +0,0 @@
{
"extends": [
"../../.eslintrc",
"plugin:vue/essential"
],
"parserOptions": {
"parser": "babel-eslint",
"ecmaVersion": 8,
"sourceType": "module"
},
"plugins": [
"vue"
],
"rules": {
"import/no-extraneous-dependencies": [
"error", {
"devDependencies": ["packages/search-site/poi.config.js"],
"optionalDependencies": false,
"peerDependencies": false
}
]
}
}

View File

@@ -1,17 +0,0 @@
# search-site
![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)
Strain search static website. Use it to search for strains by name, effects, medical uses, and other tags.
Based on data from leafly. You'll need to run the scraper first since that's where the data comes from.
## Usage
- `yarn start`: starts the dev server, with HMR
- `yarn build`: builds the static site into the `dist` path
- `yarn deploy`: builds and deploys the app onto firebase
#### License
MIT © [w33ble](https://github.com/w33ble)

View File

@@ -1,12 +0,0 @@
{
"hosting": {
"public": "dist",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}

View File

@@ -1,5 +0,0 @@
/* eslint no-global-assign: 0 */
require = require('esm')(module);
const mod = require('./src/index.mjs').default;
mod();

View File

@@ -1,3 +0,0 @@
import mod from './src/index.mjs';
mod();

View File

@@ -1,32 +0,0 @@
{
"name": "search-site",
"version": "1.1.0",
"private": true,
"main": "index",
"module": "index.mjs",
"description": "strain search static website",
"scripts": {
"start": "poi",
"build": "poi build",
"deploy": "npm run build && firebase deploy"
},
"author": "joe fleming (https://github.com/w33ble)",
"license": "MIT",
"esm": {
"cjs": true
},
"dependencies": {
"esm": "^3.0.82",
"lunr": "^2.3.3",
"vue": "^2.5.17",
"vue-router": "^3.0.1",
"vue-template-compiler": "^2.5.17"
},
"devDependencies": {
"@poi/plugin-vue-static": "^1.0.7",
"babel-eslint": "^9.0.0",
"eslint-plugin-vue": "^4.7.1",
"firebase-tools": "^4.2.1",
"poi": "^10.2.10"
}
}

View File

@@ -1,12 +0,0 @@
/* eslint global-require: 0 */
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, 'src/index.mjs'),
outDir: 'dist',
plugins: [
require('@poi/plugin-vue-static')({
routes: ['/', '/favorites'],
}),
],
};

View File

@@ -1,14 +0,0 @@
<template>
<div id="app-nav" class="tabs">
<ul>
<li class="is-active"><a>Search</a></li>
<li><a>Favorites</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'AppNav',
};
</script>

View File

@@ -1,119 +0,0 @@
<template>
<form @submit.prevent="handleSubmit">
<!-- Name Search Input -->
<div class="field">
<label class="label">Search By Name</label>
<div class="control">
<input ref="name" class="input" type="text" placeholder="Text input">
<p v-if="error.length" class="help is-danger">{{error}}</p>
</div>
</div>
<!-- Multi-Selects -->
<div class="columns filters">
<div class="column is-half">
<div class="columns is-mobile">
<div class="column is-half">
<div class="field">
<label class="label">Desired Effects</label>
<div class="select is-multiple">
<select ref="effects" multiple size="6">
<option v-for="effect in effects" :key="effect" :value="effect">{{effect | capitalize}}</option>
</select>
</div>
</div>
</div>
<div class="column is-half">
<div class="field">
<label class="label">Medical Use</label>
<div class="select is-multiple">
<select ref="uses" multiple size="6">
<option v-for="use in uses" :key="use" :value="use">{{use | capitalize}}</option>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="column is-half">
<div class="columns is-mobile">
<div class="column is-half">
<div class="field">
<label class="label">Condition</label>
<div class="select is-multiple">
<select ref="conditions" multiple size="6">
<option v-for="condition in conditions" :key="condition" :value="condition">{{condition | capitalize}}</option>
</select>
</div>
</div>
</div>
<div class="column is-half">
<div class="field">
<label class="label">Flavor</label>
<div class="select is-multiple">
<select ref="flavors" multiple size="6">
<option v-for="flavor in flavors" :key="flavor" :value="flavor">{{flavor | capitalize}}</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Form Submits -->
<div class="field is-grouped">
<div class="control">
<button type="submit" class="button is-link">Submit</button>
</div>
<div class="control">
<button type="button" class="button is-text" @click.prevent="resetForm">Clear</button>
</div>
</div>
</form>
</template>
<script>
const getMultiValues = node => Array.from(node.selectedOptions).map(o => o.value);
export default {
props: {
effects: Array,
uses: Array,
conditions: Array,
flavors: Array,
error: {
type: String,
default: '',
},
},
methods: {
handleSubmit() {
const requirements = {
name: this.$refs.name.value,
effects: getMultiValues(this.$refs.effects),
uses: getMultiValues(this.$refs.uses),
conditions: getMultiValues(this.$refs.conditions),
flavors: getMultiValues(this.$refs.flavors),
};
this.$emit('search', requirements);
},
resetForm() {
this.$el.reset();
},
},
};
</script>
<style scoped>
.filters .select {
display: block;
}
.filters .select select[multiple] {
width: 100%;
}
</style>

View File

@@ -1,88 +0,0 @@
<template>
<div class="card">
<header class="card-header">
<p class="card-header-title">{{strain.name}}</p>
<div class="tags" style="margin: 0 12px; padding: 6px 0;">
<span v-if="strain.category === 'indica'" class="tag is-rounded is-indica">{{strain.category}}</span>
<span v-if="strain.category === 'sativa'" class="tag is-rounded is-sativa">{{strain.category}}</span>
<span v-if="strain.category === 'hybrid'" class="tag is-rounded is-hybrid">{{strain.category}}</span>
<span class="tag is-rounded is-light">{{strain.rating | round}} ({{strain.rating_count}})</span>
</div>
</header>
<div class="card-content">
<TagList title="Effects" :name="strain.name" :tags="strain.effects" />
<TagList title="Uses" :name="strain.name" :tags="strain.uses" />
<TagList title="Conditions" :name="strain.name" :tags="strain.conditions" />
<TagList title="Flavors" :name="strain.name" :tags="strain.flavors" />
</div>
<footer class="card-footer">
<div class="card-footer-item">
<button
class="button"
:class="{ 'is-success': favorite }"
@click.prevent="toggleFavorite(strain.id)"
>
Save
</button>
</div>
</footer>
</div>
</template>
<script>
import store from '../lib/store.mjs';
import TagList from './TagList.vue';
export default {
components: {
TagList,
},
props: {
strain: Object,
},
data() {
const favs = store.get('favorites') || [];
return {
favorite: favs.indexOf(this.strain.id) >= 0,
};
},
methods: {
toggleFavorite() {
const isFav = !this.favorite;
const { id } = this.strain;
const favs = store.get('favorites') || [];
const idx = favs.indexOf(id);
// update component state
this.favorite = isFav;
// update the store
if (idx >= 0 && !isFav) {
// remove previously favorited strain
store.set('favorites', favs.filter(f => f !== id));
} else if (idx === -1 && isFav) {
// add new favorited strain
store.set('favorites', favs.concat(id));
}
},
},
};
</script>
<style scoped>
.tag.is-indica {
background-color: hsl(217, 71%, 53%);
color: #fff;
}
.tag.is-sativa {
background-color: hsl(348, 100%, 61%);
color: #fff;
}
.tag.is-hybrid {
background-color: hsl(271, 100%, 71%);
color: #fff;
}
</style>

View File

@@ -1,62 +0,0 @@
<template>
<div>
<div>
<h3 v-show="strains.length === 0" class="title is-3">No Matching Strains :(</h3>
<h3 v-show="strains.length > 0" class="title is-3">Found {{strains.length}} Strains</h3>
</div>
<div class="cards">
<StrainCard v-for="strain in strains" :key="strain.id" :strain="strain" />
</div>
</div>
</template>
<script>
import StrainCard from './StrainCard.vue';
export default {
components: {
StrainCard,
},
props: {
strains: {
type: Array,
required: true,
},
},
};
</script>
<style scoped>
.cards {
display: flex;
flex-wrap: wrap;
}
.cards .card {
width: 100%;
margin: 12px;
}
.cards .card .tag-list--title {
font-size: 0.8em;
}
@media screen and (min-width: 769px) {
.cards .card {
width: 45%;
}
}
@media screen and (min-width: 1280px) {
.cards .card {
width: 30%;
}
}
@media screen and (max-width: 860px) {
.cards .card .tag-list--title {
font-size: 0.7em;
}
}
</style>

View File

@@ -1,22 +0,0 @@
<template>
<div v-if="tags.length" class="tag-list columns is-mobile">
<div class="tag-list--title column is-one-quarter">
{{title}}
</div>
<div class="tag-list--tag column">
<div v-if="tags.length" class="tags">
<span v-for="tag in tags" :key="name + tag" class="tag is-rounded">{{tag}}</span>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
tags: Array,
title: String,
name: String,
},
};
</script>

View File

@@ -1,12 +0,0 @@
import Vue from 'vue';
Vue.filter('capitalize', value => {
if (!value) return '';
const v = value.toString();
return v.charAt(0).toUpperCase() + v.slice(1);
});
Vue.filter('round', (value, digits = 2) => {
const v = parseFloat(value, 10);
return Math.round(v * (10 * digits)) / (10 * digits);
});

View File

@@ -1,51 +0,0 @@
import Vue from 'vue';
import Router from 'vue-router';
import './filters.mjs';
import strainData from './plugins/strainData.mjs';
import lunr from './plugins/lunr.mjs';
Vue.use(strainData);
Vue.use(
lunr(function lunrSetup() {
// lunr search index setup
this.ref('id');
this.field('name');
this.field('effects');
this.field('uses');
this.field('conditions');
this.field('flavors');
Vue.prototype.$strainData.strains.forEach(doc => this.add(doc));
})
);
Vue.use(Router);
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
component: () => import(/* webpackChunkName: "Home" */ './pages/Home.vue'),
children: [
{
path: '',
name: 'search',
component: () => import(/* webpackChunkName: "Search" */ './pages/Search.vue'),
},
{
path: 'favorites',
name: 'favorites',
component: () => import(/* webpackChunkName: "Favorites" */ './pages/Favorites.vue'),
},
],
},
],
});
const app = new Vue({
router,
render: h => h('div', { attrs: { id: 'app' } }, [h('router-view')]),
});
export default app;

View File

@@ -1,18 +0,0 @@
/* eslint-env browser */
const storage = (() => {
try {
return window.localStorage;
} catch (err) {
// return a mock localstorage in the server env
return {
getItem: () => null,
setItem: () => null,
};
}
})();
export default {
get: id => JSON.parse(storage.getItem(id)),
set: (id, val) => storage.setItem(id, JSON.stringify(val)),
};

View File

@@ -1,43 +0,0 @@
<template>
<div id="favorites-page">
<div class="container">
<h1 class="title">
Favorites
</h1>
<h3 class="title is-5">
Strains you have saved
</h3>
</div>
<section class="section">
<div class="container">
<StrainList :strains="favoriteStrains" no-save-control />
</div>
</section>
</div>
</template>
<script>
import store from '../lib/store.mjs';
import StrainList from '../components/StrainList.vue';
export default {
name: 'FavoritesPage',
components: {
StrainList,
},
data() {
const favorites = store.get('favorites') || [];
return {
favorites,
};
},
computed: {
favoriteStrains() {
return this.$strainData.strains.filter(strain => this.favorites.indexOf(strain.id) !== -1);
},
},
};
</script>

View File

@@ -1,40 +0,0 @@
<template>
<div id="home-page">
<div id="app-nav" class="tabs is-centered">
<ul>
<li :class="{'is-active': activeTab === 'search'}" @click="setActive('search')">
<router-link :to="{name: 'search'}">Search</router-link>
</li>
<li :class="{'is-active': activeTab === 'favorites'}" @click="setActive('favorites')">
<router-link :to="{name: 'favorites'}">Favorites</router-link>
</li>
</ul>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'HomePage',
data() {
return {
activeTab: this.$route.name,
};
},
methods: {
setActive(name) {
this.activeTab = name;
},
},
head: {
title: 'Strain Search',
link: [
{
rel: 'stylesheet',
href: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css',
},
],
},
};
</script>

View File

@@ -1,140 +0,0 @@
<template>
<div id="search-page">
<div class="container">
<h1 class="title">
Strain Search
</h1>
</div>
<section class="section">
<div class="container">
<SearchForm
:effects="effects"
:uses="uses"
:conditions="conditions"
:flavors="flavors"
:error="error"
@search="onSearch"
/>
</div>
</section>
<section class="section">
<div class="container">
<StrainList :strains="matches" />
</div>
</section>
</div>
</template>
<script>
import SearchForm from '../components/SearchForm.vue';
import StrainList from '../components/StrainList.vue';
export default {
name: 'SearchPage',
components: {
SearchForm,
StrainList,
},
data() {
return {
error: '',
matches: [],
requirements: {
name: '',
effects: [],
uses: [],
conditions: [],
flavors: [],
},
};
},
computed: {
strains() {
return this.$strainData.strains;
},
effects() {
return this.$strainData.effects;
},
uses() {
return this.$strainData.uses;
},
conditions() {
return this.$strainData.conditions;
},
flavors() {
return this.$strainData.flavors;
},
hasName() {
return this.requirements.name.length > 0;
},
hasFilters() {
return (
this.requirements.effects.length > 0 ||
this.requirements.uses.length > 0 ||
this.requirements.conditions.length > 0 ||
this.requirements.flavors.length > 0
);
},
searchParams() {
const searchParts = [this.requirements.name];
this.requirements.effects.forEach(t => searchParts.push(`+effects:${t}`));
this.requirements.uses.forEach(t => searchParts.push(`+uses:${t}`));
this.requirements.conditions.forEach(t => searchParts.push(`+conditions:${t}`));
this.requirements.flavors.forEach(t => searchParts.push(`+flavors:${t}`));
return searchParts.join(' ');
},
},
methods: {
onSearch(reqs) {
this.requirements = reqs;
this.updateMatches();
},
showDefaults(limit = 40) {
// const favs = store.get('favorites') || [];
// const favStrains = this.strains.filter(({ id }) => favs.indexOf(id) !== -1);
// this.matches = favStrains.concat(this.strains.slice(0, limit - favStrains.length));
this.matches = this.strains.slice(0, limit);
},
updateMatches(limit = 40) {
this.error = '';
if (!this.hasName && !this.hasFilters) {
this.showDefaults(limit);
return;
}
try {
const hits = this.$lunr.search(this.searchParams);
// .slice(0, limit);
const refs = hits.map(({ ref }) => parseInt(ref, 10));
this.matches = this.strains
.map(strain => {
const idx = refs.indexOf(strain.id);
if (idx < 0) return null;
return Object.assign({ score: hits[idx].score }, strain);
})
.filter(Boolean)
.sort((a, b) => {
if (a.score === b.score) {
// sort matching search score by adjusted rating
if (a.rating_adjusted === b.rating_adjusted) return 0;
return a.rating_adjusted > b.rating_adjusted ? -1 : 1;
}
return a.score > b.score ? -1 : 1;
});
} catch (err) {
this.matches = [];
this.error = err.message;
}
},
},
created() {
this.updateMatches(); // set initial match list
},
};
</script>

View File

@@ -1,10 +0,0 @@
/* eslint no-param-reassign: 0 */
import lunr from 'lunr';
export default function(lunrSetup) {
return {
install(Vue) {
Vue.prototype.$lunr = lunr(lunrSetup);
},
};
}

View File

@@ -1,8 +0,0 @@
/* eslint no-param-reassign: 0 */
import data from '../../../scraper/db.json';
export default {
install(Vue) {
Vue.prototype.$strainData = data;
},
};

View File

@@ -1,26 +0,0 @@
import fs from 'fs';
import { promisify } from 'util';
import { join } from 'path';
import pkg from '../package.json';
const readDir = promisify(fs.readdir);
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
async function syncPackageVersions() {
const packagesPath = 'packages'; // path for all packages
const { version } = pkg;
const packages = await readDir(packagesPath);
packages.forEach(async pack => {
const packagePath = join(packagesPath, pack, 'package.json');
const p = JSON.parse(await readFile(packagePath, 'utf-8'));
p.version = version;
await writeFile(packagePath, `${JSON.stringify(p, null, 2)}\n`);
});
console.log(`Versions with root: ${version}`);
}
syncPackageVersions();

6357
yarn.lock

File diff suppressed because it is too large Load Diff