Skip to content

Commit

Permalink
feat: Added FishTankLookup
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Akpa committed Apr 2, 2019
1 parent c27d48d commit afb08c4
Show file tree
Hide file tree
Showing 10 changed files with 527 additions and 2 deletions.
1 change: 1 addition & 0 deletions dev/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<li><a href="#/pagination">Pagination</a></li>
<li><a href="#/box">Box</a></li>
<li><a href="#/select">Select</a></li>
<li><a href="#/lookup">Lookup</a></li>
</ul>
</section>
</template>
4 changes: 4 additions & 0 deletions dev/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export default new Router(<RouterOptions>{
{
path: '/alerts',
component: () => import("./views/Alerts.vue")
},
{
path: '/lookup',
component: () => import("./views/Lookup.vue")
}
]
})
52 changes: 52 additions & 0 deletions dev/views/Lookup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<template>
<div>
<Autocomplete
id="autocomplete_example"
label="Autocomplete Label"
orientation="ltr"
url="/some_autocomplete_endpoint"
v-model="selected" />
<div v-if="selected">{{selected.label}}</div>
</div>
</template>
<script>
const moxios = require('moxios')
import { FishTankLookup } from '@/index';
export default {
components:{
Autocomplete:FishTankLookup
},
data () {
return {
selected: null
}
},
created () {
moxios.install()
moxios.stubRequest(/\/some_autocomplete_endpoint\?query=.+$/, {
status: 200,
response: {
"data": {
"items": [
{ label: "Some item 1", value: "Some item 1" },
{ label: "Some item 2", value: "Some item 2" },
{ label: "Some item 3", value: "Some item 3" },
{ label: "Some item 4", value: "Some item 4" },
{ label: "Some item 5", value: "Some item 5" }
]
}
}
})
// Mock empty request
moxios.stubRequest(/\/some_autocomplete_endpoint\?query=$/, {
status: 200,
response: {
"data": {
"items": []
}
}
})
}
}
</script>
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@fishtank/icons-vue": "3.11.0",
"@fishtank/space": "1.3.0",
"@fishtank/type": "3.1.0",
"axios": "0.18.0",
"tslib": ">= 1.9.0",
"vue-content-loader": "^0.2.1",
"vue-runtime-helpers": "1.0.0",
Expand Down Expand Up @@ -78,6 +79,7 @@
"extract-text-webpack-plugin": "3.0.2",
"in-publish": "2.0.0",
"lodash": ">=4.17.11",
"moxios": "0.4.0",
"node-sass": "4.9.0",
"normalize-scss": "7.0.1",
"postcss": "7.0.6",
Expand Down
95 changes: 95 additions & 0 deletions src/components/BLAWDataFetcher.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<script>
import axios from 'axios'
/** Event fired on request error
* @event error
* @type {Event}
*/
/** Triggered when request succeeds and pass server response
* @event success
* @type {Event}
*/
export default {
name: 'DataFetcher',
data () {
return {
cache: {},
fetchedData: { data: {} },
lastRequest: '',
loading: false
}
},
props: {
/**
* Enable request caching
*/
enableCache: Boolean,
/**
* Url to request data from, will make new request when changed
*/
url: String
},
watch: {
url (newValue) {
this.lastRequest = newValue
if (!this.loading && newValue) this._request(newValue)
}
},
methods: {
/**
* Force refetch (clears cached value before fetching)
*/
refetch () {
return new Promise((resolve, reject) => {
delete this.cache[this.url]
this.lastRequest = this.url
this._request(this.url).then(resolve).catch(reject)
})
},
_request (url) {
return new Promise((resolve, reject) => {
this.loading = true
if (this.cache[url]) {
this.fetchedData = this.cache[url]
this.loading = false
resolve(this.fetchedData)
} else {
axios
.get(url)
.then(res => {
this.fetchedData = res.data
if (this.enableCache) this.cache[url] = res.data
this.$emit('success', res)
resolve(res.data)
})
.catch(res => {
this.$emit('error', res)
reject(res.data)
})
.finally(() => {
this.loading = false
if (this.lastRequest !== url) this._request(this.lastRequest)
})
}
})
}
},
render () {
return this.$scopedSlots.default({
loading: this.loading,
fetchedData: this.fetchedData
})
},
created () {
if (this.url) {
this.lastRequest = this.url
this._request(this.url)
}
}
}
</script>
27 changes: 27 additions & 0 deletions src/components/BLAWHighlightedText.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<span class="HighlightedText" v-html="_transformedContent" />
</template>

<script>
export default {
name: 'HighlightedText',
props: {
content: String,
term: String
},
computed: {
_transformedContent () {
return this.content.replace(new RegExp(`(${this.term})`, 'ig'), `<mark class="highlight">$1</mark>`)
}
}
}
</script>

<style scoped lang="scss">
.HighlightedText {
& /deep/ .highlight {
background-color: var(--highlight-color, #FFE1A0);
color: var(--invert-hightlight-color, #333);
}
}
</style>
151 changes: 151 additions & 0 deletions src/components/BLAWTextInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<template>
<div class="TextInput" :name="name" :orientation="orientation" @blur="$refs.input.blur()">
<label v-if="label">{{label}}</label>
<div class="input-wrapper">
<slot name="icon">
<!-- <FishtankIcon v-if="icon" color="#777C7F" :name="icon" width="24" height="24" /> -->
</slot>
<input
autocomplete="new-password"
ref="input"
type="text"
:id="id"
:placeholder="placeholder"
:value="value"
@blur="$emit('blur', $event)"
@focus="$emit('focus', $event)"
@input="$emit('input', $event.target.value)"
/>
<slot name="below" />
</div>
</div>
</template>

<script>
// import FishtankIcon from './fishtank/FishtankIcon.vue'
/** Triggered input element is blurred
* @event blur
* @type {Event}
*/
/** Triggered input element is focused
* @event focus
* @type {Event}
*/
/** Triggered input element is changed (compatible with v-model)
* @event input
* @type {Event}
*/
/**
* Default text input element.
* NOTE: Uses autocomplete="new-password" to disable native autocomplete from Chrome
*/
export default {
name: 'TextInput',
// components: { FishtankIcon },
props: {
/**
* Input element id
*/
id: String,
/**
* Icon to display in input box
*/
icon: String,
/**
* Label to display with input
*/
label: String,
/**
* Orientation to display with label/input (ie ttb, rtl, ltr)
*/
orientation: {
type: String,
default: 'ttb'
},
/**
* Input element name
*/
name: String,
/**
* Placeholder to display
*/
placeholder: String,
/**
* Current value
*/
value: String
}
}
</script>

<style scoped lang="scss">
.TextInput {
label {
color: var(--primary-color, #777c7f);
cursor: pointer;
display: inline-flex;
font-family: var(--font-family, 'Open Sans', sans-serif);
line-height: 26px;
width: var(--label-width, auto);
}
&[orientation='ltr'] {
align-items: center;
display: flex;
label { margin-right: 10px; }
}
&[orientation='rtl'] {
align-items: center;
display: flex;
flex-direction: row-reverse;
label { margin-left: 10px; }
}
.input-wrapper {
display: flex;
flex-grow: 1;
position: relative;
.FishtankIcon {
left: 6px;
position: absolute;
top: 8px;
+input[type=text] { padding-left: 32px; }
}
input[type=text] {
border-radius: 3px;
border: 1px solid var(--border-color, #C5CACD);
flex-grow: 1;
font-family: var(--font-family, 'Open Sans', sans-serif);
font-size: 16px;
padding: 10px;
&:focus {
border: 1px solid #0D9DDB;
box-shadow: inset 0 0 0 1px #0D9DDB;
outline: none;
}
&::placeholder {
color: #C5CACD;
font-style: italic;
}
}
}
}
</style>
Loading

0 comments on commit afb08c4

Please sign in to comment.