adding tags handle

main
HerrHase 2 years ago
parent e380f34c21
commit 6770faf4fe

@ -1,5 +1,5 @@
<potato-close-button> <potato-close-button>
<button class="button button--icon button--danger button--hover-icon-contrast m-left-4 m-bottom-0" onclick={ (event) => { handleClose(event) } }> <button class="button button--full button--icon button--danger m-bottom-0" onclick={ (event) => { handleClose(event) } }>
<svg class="icon icon--big" aria-hidden="true"> <svg class="icon icon--big" aria-hidden="true">
<use xlink:href="symbol-defs.svg#icon-log-out"></use> <use xlink:href="symbol-defs.svg#icon-log-out"></use>
</svg> </svg>

@ -1,24 +1,45 @@
<potato-filter> <potato-filter>
<div class="filter"> <div class="{ getCssClasses('filter') }">
<button class="button button--icon button--hover-icon-contrast m-bottom-0"> <div class="display-flex">
<svg class="icon icon--big"> <button class="button button--open button--icon button--hover-icon-contrast m-bottom-0" onclick={ (event) => { handleOpen(event) }}>
<use xlink:href="symbol-defs.svg#icon-filter" /> <svg class="icon icon--big">
</svg> <use xlink:href="symbol-defs.svg#icon-filter" />
</button> </svg>
<div class=""> </button>
<div class=""> <button class="button button--close button--icon button--hover-icon-contrast m-bottom-0" onclick={ (event) => { handleOpen(event) }}>
<svg class="icon icon--big">
</div> <use xlink:href="symbol-defs.svg#icon-close" />
<div class=""> </svg>
</button>
<div class="filter__selected m-left-3" if={ state.tags.length > 0 }>
<button if={ tag.selected === true } class="button m-bottom-0 m-right-3" each={ (tag, index) in state.tags } onclick={ (event) => { handleToggle(event, index) }}>
{ tag.name }
<svg class="icon">
<use xlink:href="symbol-defs.svg#icon-close" />
</svg>
</button>
</div> </div>
</div> </div>
<div class="filter__tags">
<button class="button" each={ (tag, index) in state.tags } onclick={ (event) => { handleToggle(event, index) }}>
{ tag.name }
<svg class="icon { tag.selected ? 'hidden' : '' }">
<use xlink:href="symbol-defs.svg#icon-checkbox" />
</svg>
<svg class="icon { tag.selected === undefined ? 'hidden' : '' }">
<use xlink:href="symbol-defs.svg#icon-checkbox-checked" />
</svg>
</button>
</div>
</div> </div>
<script> <script>
import tagsStore from './../stores/tags.js'
import appsStore from './../stores/apps.js'
/** /**
* close app *
* *
* @author Björn Hase * @author Björn Hase
* @license hhttps://www.gnu.org/licenses/gpl-3.0.en.html GPL-3 * @license hhttps://www.gnu.org/licenses/gpl-3.0.en.html GPL-3
@ -27,7 +48,78 @@
*/ */
export default { export default {
state: {
tags: [],
selected: [],
isOpen: false
},
/**
*
*
*/
getCssClasses(defaultCssClass) {
const classes = [
defaultCssClass
]
if (this.state.isOpen === true) {
classes.push('filter--open')
}
return classes.join(' ')
},
/**
*
*
*/
onMounted() {
tagsStore.on('ready', (data) => {
this.state.tags = data
this.update()
})
tagsStore.get()
},
/**
* toggle
*
* @param {object} event
* @param {integer} index
*
*/
handleToggle(event, index) {
if (this.state.tags[index].selected === undefined) {
this.state.tags[index].selected = true
this.state.selected.push(this.state.tags[index].name)
} else {
const selectedIndex = this.state.selected.indexOf(this.state.tags[index].name)
// delete selected from tags
delete this.state.tags[index].selected
if (selectedIndex !== -1) {
this.state.selected.splice(selectedIndex, 1)
}
}
appsStore.filter(this.state.selected)
this.update()
},
handleOpen(event) {
if (this.state.isOpen === true) {
this.state.isOpen = false
} else {
this.state.isOpen = true
}
this.update()
}
} }
</script> </script>

@ -1,11 +1,11 @@
<potato-sorting> <potato-sorting>
<div class="filter"> <div class="filter">
<button class="button button--icon button--hover-icon-contrast m-bottom-0" if={ state.orderBy === 'name' } onclick={ (event) => { handleToggle(event) }}> <button class="button button--icon button--hover-icon-contrast m-bottom-0" if={ state.column === 'name' } onclick={ (event) => { handleToggle(event) }}>
<svg class="icon icon--big"> <svg class="icon icon--big">
<use xlink:href="symbol-defs.svg#icon-text" /> <use xlink:href="symbol-defs.svg#icon-text" />
</svg> </svg>
</button> </button>
<button class="button button--icon button--hover-icon-contrast m-bottom-0" if={ state.orderBy === 'date_started' } onclick={ (event) => { handleToggle(event) }}> <button class="button button--icon button--hover-icon-contrast m-bottom-0" if={ state.column === 'date_started' } onclick={ (event) => { handleToggle(event) }}>
<svg class="icon icon--big"> <svg class="icon icon--big">
<use xlink:href="symbol-defs.svg#icon-clock" /> <use xlink:href="symbol-defs.svg#icon-clock" />
</svg> </svg>
@ -14,6 +14,8 @@
<script> <script>
import appsStore from './../stores/apps.js'
/** /**
* sorting of apps * sorting of apps
* *
@ -24,19 +26,29 @@
*/ */
export default { export default {
state: { state: {
orderBy: 'name' column: 'name'
}, },
/**
* toggle sorting
*
*
* @param {[type]} event
*
*/
handleToggle(event) { handleToggle(event) {
event.preventDefault() event.preventDefault()
if (this.state.orderBy === 'name') { if (this.state.column === 'name') {
this.state.orderBy = 'date_started' this.state.column = 'date_started'
} else if (this.state.orderBy = 'date_started') { } else if (this.state.column === 'date_started') {
this.state.orderBy = 'name' this.state.column = 'name'
} }
appsStore.sort(this.state.column)
this.update() this.update()
} }
} }

@ -1,4 +1,5 @@
import DatabaseHandler from './databaseHandler.js' import DatabaseHandler from './databaseHandler.js'
import TagsDatabase from './tags.js'
/** /**
* apps * apps
@ -11,14 +12,17 @@ import DatabaseHandler from './databaseHandler.js'
class AppsDatabase extends DatabaseHandler { class AppsDatabase extends DatabaseHandler {
constructor() { constructor() {
super() super('apps')
// add index for apps // add index for apps to sort by name
this.createIndex([ this.createIndex([
'name', 'name'
'description', ], 'name-sort')
'tags'
]) // add index for apps to sort by name
this.createIndex([
'date_started'
], 'date-started-sort')
} }
/** /**
@ -28,8 +32,17 @@ class AppsDatabase extends DatabaseHandler {
* *
*/ */
create(data) { create(data) {
data.date_started = 0
return this.db.post(data) return this.db.post(data)
.then((response) => { .then((response) => {
if (data.tags) {
const tagsDatabase = new TagsDatabase()
tagsDatabase.update(data.tags)
}
return this.findOneById(response._id) return this.findOneById(response._id)
}).catch((error) => { }).catch((error) => {
console.error(error) console.error(error)
@ -67,7 +80,8 @@ class AppsDatabase extends DatabaseHandler {
'command', 'command',
'description', 'description',
'thumbnail', 'thumbnail',
'tags' 'tags',
'date_started'
], ],
'selector': { 'selector': {
'_id' : id '_id' : id
@ -91,7 +105,8 @@ class AppsDatabase extends DatabaseHandler {
* @return {mixed} * @return {mixed}
* *
*/ */
find(sorting = 'name', tags = []) { find(parameters) {
const query = { const query = {
'fields': [ 'fields': [
'_id', '_id',
@ -102,13 +117,36 @@ class AppsDatabase extends DatabaseHandler {
'thumbnail', 'thumbnail',
'tags', 'tags',
'date_started' 'date_started'
], ]
'selector': { }
'name': {
'$exists': true // adding sort from parameters
if (parameters.sort) {
query.sort = []
query.sort.push(parameters.sort)
if (parameters.sort === 'date_started') {
query.use_index = '_design/date-started-sort'
query.selector = {
'date_started': {
'$regex': ''
}
} }
}, } else {
'sort': [ sorting ] query.use_index = '_design/name-sort'
query.selector = {
'name': {
'$regex': ''
}
}
}
}
// adding tags from parameters
if (parameters.tags.length > 0) {
query.selector.tags = {
$in: parameters.tags
}
} }
return this.db.find(query).then((documents) => { return this.db.find(query).then((documents) => {
@ -116,6 +154,10 @@ class AppsDatabase extends DatabaseHandler {
console.warning(documents.warning) console.warning(documents.warning)
} }
if (documents.docs.length > 0 && parameters.tags.length > 0) {
}
return documents.docs return documents.docs
}).catch((error) => { }).catch((error) => {
console.error(error) console.error(error)

@ -16,10 +16,10 @@ class DatabaseHandler {
* *
* *
*/ */
constructor() { constructor(name) {
PouchDB.plugin(PouchDBfind) PouchDB.plugin(PouchDBfind)
this.db = new PouchDB('apps', { this.db = new PouchDB(name, {
revs_limit: 0 revs_limit: 0
}) })
} }
@ -30,17 +30,22 @@ class DatabaseHandler {
* @param {array} fields * @param {array} fields
* *
*/ */
createIndex(fields) { createIndex(fields, name = null) {
// adding index // adding index
try { try {
this.db.createIndex({
const query = {
index: { index: {
fields: fields fields: fields
} }
}).then(() => { }
if (name) {
query.index.ddoc = name
}
}) this.db.createIndex(query)
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }

@ -11,12 +11,12 @@ import DatabaseHandler from './databaseHandler.js'
class TagsDatabase extends DatabaseHandler { class TagsDatabase extends DatabaseHandler {
constructor() { constructor() {
super() super('tags')
// add index for apps // add index for apps
this.createIndex([ this.createIndex([
'name' 'name'
]) ], 'tags')
} }
/** /**
@ -25,7 +25,7 @@ class TagsDatabase extends DatabaseHandler {
* @param {object} data * @param {object} data
* *
*/ */
async create(tags) { async update(tags) {
const query = { const query = {
'selector': { 'selector': {
@ -40,9 +40,10 @@ class TagsDatabase extends DatabaseHandler {
// check for existings tags and remove // check for existings tags and remove
// adding tags that are not removed // adding tags that are not removed
this.db.find(query).then((documents) => { this.db.find(query).then((documents) => {
if (documents.docs && documents.docs.length > 0) { if (documents.docs.length > 0) {
documents.docs.forEach(data, () => { documents.docs.forEach((data) => {
// getting
const index = tags.indexOf(data.name) const index = tags.indexOf(data.name)
if (index >= 0) { if (index >= 0) {
@ -53,7 +54,7 @@ class TagsDatabase extends DatabaseHandler {
if (tags.length > 0) { if (tags.length > 0) {
tags.forEach((tag) => { tags.forEach((tag) => {
await this.db.post({ this.db.post({
'name': tag 'name': tag
}) })
}) })
@ -62,61 +63,32 @@ class TagsDatabase extends DatabaseHandler {
} }
/** /**
* find apps
* *
* *
* @param {object} data * @return
* *
*/ */
async remove(tags) { find() {
const query = { const query = {
'fields': [
'name'
],
'selector': { 'selector': {
'name': { 'name': {
'$in': tags '$exists': true
} }
}, 'fields': [ },
'sort': [
'name' 'name'
] ]
} }
// check for existings tags and remove return this.db.find(query).then((documents) => {
// adding tags that are not removed if (documents.warning) {
this.db.find(query).then((documents) => { console.warning(documents.warning)
if (documents.docs && documents.docs.length > 0) {
documents.docs.forEach(data, () => {
const index = tags.indexOf(data.name)
if (index >= 0) {
tags.splice(index, 1)
}
})
}
if (tags.length > 0) {
tags.forEach((tag) => {
await this.db.post({
'name': tag
})
})
} }
})
}
/**
* find apps
*
* @return {mixed}
*
*/
find() {
const query = {
'fields': [
'name'
]
}
return this.db.find(query).then((documents) => {
return documents.docs return documents.docs
}) })
} }

@ -12,14 +12,29 @@ import observable from '@riotjs/observable'
export default observable({ export default observable({
parameters: {
sort: 'name',
tags: []
},
/**
* getting all apps
*
*/
get() { get() {
const appsDatabase = new AppsDatabase() const appsDatabase = new AppsDatabase()
appsDatabase.find().then((data) => { appsDatabase.find(this.parameters).then((data) => {
this.trigger('ready', data) this.trigger('ready', data)
}) })
}, },
/**
* getting single apps
*
* @param {uuid} id
*
*/
getOne(id) { getOne(id) {
const appsDatabase = new AppsDatabase() const appsDatabase = new AppsDatabase()
@ -28,6 +43,12 @@ export default observable({
}) })
}, },
/**
* create new app
*
* @param {object} data
*
*/
post(data) { post(data) {
const appsDatabase = new AppsDatabase() const appsDatabase = new AppsDatabase()
@ -36,12 +57,40 @@ export default observable({
}) })
}, },
/**
* update app
*
* @param {object} data
*
*/
put(data) { put(data) {
const appsDatabase = new AppsDatabase() const appsDatabase = new AppsDatabase()
appsDatabase.update(data).then((data) => { appsDatabase.update(data).then((data) => {
this.trigger('success', data) this.trigger('success', data)
}) })
},
/**
* orderBy and run get
*
* @param {string} orderBy
*
*/
sort(column) {
this.parameters.sort = column
this.get()
},
/**
* filter and run get
*
* @param {array} tags
*
*/
filter(tags) {
this.parameters.tags = tags
this.get()
} }
}) })

@ -1,5 +1,5 @@
/** /**
* Store for apps *
* *
* @author Björn Hase * @author Björn Hase
* @license hhttps://www.gnu.org/licenses/gpl-3.0.en.html GPL-3 * @license hhttps://www.gnu.org/licenses/gpl-3.0.en.html GPL-3
@ -7,8 +7,20 @@
* *
*/ */
import observable from '@riotjs/observable' import TagsDatabase from './../database/tags.js'
import observable from '@riotjs/observable'
export default observable({
export default observable({ /**
* getting all apps
*
*/
get() {
const tagsDatabase = new TagsDatabase()
}) tagsDatabase.find().then((data) => {
this.trigger('ready', data)
})
}
})

@ -8,7 +8,7 @@
<potato-filter></potata-filter> <potato-filter></potata-filter>
</div> </div>
<div> <div>
<potato-apps-form-button></potato-apps-form-button> <potato-apps-form-button class="m-right-3"></potato-apps-form-button>
<potato-close-button></potato-close-button> <potato-close-button></potato-close-button>
</div> </div>
</div> </div>

@ -1,3 +1,7 @@
.justify-content-space-between { .justify-content-space-between {
justify-content: space-between; justify-content: space-between;
}
.hidden {
display: none;
} }

@ -0,0 +1,67 @@
.filter {
&__tags {
visibility: hidden;
position: absolute;
z-index: 100;
margin: 1em 0 0;
.button {
display: block;
margin-right: 1em;
.icon {
vertical-align: sub;
margin: 0 -0.25em 0 0.25em;
}
}
}
&:after {
content: '';
position: fixed;
left: 0;
top:0;
z-index: 99;
visibility: hidden;
width: 100%;
height: 100%;
background-color: #04040480;
}
.button--close {
display: none;
}
&__selected {
.button {
color: white;
padding: 0.8em 1.2em;
background: #878787;
.icon {
fill: white;
margin: 0 -0.25em 0 0.25em
}
}
}
&--open {
&:after {
visibility: visible;
}
.filter__tags {
visibility: visible;
}
.button--close {
display: inline-flex;
z-index: 101;
}
.button--open {
display: none;
}
}
}

@ -10,5 +10,6 @@
'components/field-tags', 'components/field-tags',
'components/loading', 'components/loading',
'components/buttons', 'components/buttons',
'components/filter',
'components/icons'; 'components/icons';

Loading…
Cancel
Save