Compare commits
6 Commits
b3f21184c6
...
333c91b4c6
Author | SHA1 | Date | |
---|---|---|---|
333c91b4c6 | |||
906bcd5493 | |||
79b88d7a59 | |||
f559c237ca | |||
52bc6febaa | |||
3e1695e6f3 |
15
src/App.vue
15
src/App.vue
|
@ -5,14 +5,13 @@
|
||||||
<div class="navbar-brand">
|
<div class="navbar-brand">
|
||||||
<router-link to="/" class="navbar-item">Ekster</router-link>
|
<router-link to="/" class="navbar-item">Ekster</router-link>
|
||||||
|
|
||||||
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false">
|
<a role="button" :class="{'navbar-burger':true,'is-active':menuActive}" aria-label="menu" aria-expanded="false" @click="toggleMenu">
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-menu">
|
<div :class="{'navbar-menu':true,'is-active':menuActive}">
|
||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button class="button is-light" @click="openSearch">Search</button>
|
<button class="button is-light" @click="openSearch">Search</button>
|
||||||
|
@ -42,10 +41,18 @@
|
||||||
this.$store.dispatch('startEventListening', '?action=events')
|
this.$store.dispatch('startEventListening', '?action=events')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
menuActive() {
|
||||||
|
return this.$store.state.menuActive
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openSearch () {
|
openSearch () {
|
||||||
this.$store.dispatch('openSearch')
|
this.$store.dispatch('openSearch')
|
||||||
}
|
},
|
||||||
|
toggleMenu () {
|
||||||
|
this.$store.dispatch('toggleMenu' )
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="channels--channel" v-for="channel in channels" :key="channel.uid">
|
<div class="channels--channel" v-for="channel in channels" :key="channel.uid">
|
||||||
<slot :channel="channel"></slot>
|
<slot :channel="channel"></slot>
|
||||||
</div>
|
</div>
|
||||||
<button class="button is-primary" @click="open">+ New Channel</button>
|
<button class="button is-primary is-small" @click="open">New Channel</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -216,15 +216,18 @@ export default {
|
||||||
},
|
},
|
||||||
toggleHiddenContent() {
|
toggleHiddenContent() {
|
||||||
this.hiddenContentVisible = !this.hiddenContentVisible
|
this.hiddenContentVisible = !this.hiddenContentVisible
|
||||||
const el = this.$refs['content-container']
|
// const el = this.$refs['content-container']
|
||||||
el.scrollIntoView(true)
|
// el.scrollIntoView(true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.showFooterButtons = true
|
this.showFooterButtons = true
|
||||||
const el = this.$refs['content-container']
|
const el = this.$refs['content-container']
|
||||||
this.hasHiddenContent = el.scrollHeight > el.clientHeight
|
this.hiddenContentVisible = false
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.hasHiddenContent = el.scrollHeight > el.clientHeight
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -377,8 +380,10 @@ export default {
|
||||||
console.log('ref content-container not found')
|
console.log('ref content-container not found')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.hasHiddenContent = el.scrollHeight > el.clientHeight
|
|
||||||
this.hiddenContentVisible = false
|
this.hiddenContentVisible = false
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.hasHiddenContent = el.scrollHeight > el.clientHeight
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,14 @@
|
||||||
<button :class="searchClasses" @click="search">Search</button>
|
<button :class="searchClasses" @click="search">Search</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<label for="global" class="radio"><input type="radio" name="channel" id="global" value="global" v-model="searchChannel"> Global</label>
|
||||||
|
<label for="channel" class="radio"><input type="radio" name="channel" id="channel" value="channel" v-model="searchChannel"> Channel</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="timeline--item" v-for="item in searchItems" :key="item.id">
|
<div class="timeline--item" v-for="item in searchItems" :key="item.id">
|
||||||
<TimelineEntry :item="item" :is-main-entry="true" @debug="debug" />
|
<TimelineEntry :item="item" :is-main-entry="true" @debug="debug" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +45,8 @@ export default {
|
||||||
return {
|
return {
|
||||||
query: '',
|
query: '',
|
||||||
loading: false,
|
loading: false,
|
||||||
error: ''
|
error: '',
|
||||||
|
searchChannel: 'global'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
@ -65,7 +73,7 @@ export default {
|
||||||
search () {
|
search () {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.error = ''
|
this.error = ''
|
||||||
this.$store.dispatch('startQuery', this.query)
|
this.$store.dispatch('startQuery', {query: this.query, channel: this.searchChannel})
|
||||||
.then(result => {
|
.then(result => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
<TimelineEntry :item="item" @debug="debug" @markRead="markRead(channel.uid, ...arguments)" @followFeed="$emit('followFeed', arguments[0])"
|
<TimelineEntry :item="item" @debug="debug" @markRead="markRead(channel.uid, ...arguments)" @followFeed="$emit('followFeed', arguments[0])"
|
||||||
:is-main-entry="true"/>
|
:is-main-entry="true"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="items.length === 0">
|
||||||
|
<p class="text-center">No items in this timeline</p>
|
||||||
|
</div>
|
||||||
<div class="level">
|
<div class="level">
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<button class="button" @click="prevPage" v-if="timeline.paging.before">Prev Page</button>
|
<button class="button" @click="prevPage" v-if="timeline.paging.before">Prev Page</button>
|
||||||
|
|
66
src/store.js
66
src/store.js
|
@ -22,7 +22,8 @@ export default new Vuex.Store({
|
||||||
globalTimeline: {items: []},
|
globalTimeline: {items: []},
|
||||||
debug: false,
|
debug: false,
|
||||||
debugItem: {},
|
debugItem: {},
|
||||||
debugVisible: false
|
debugVisible: false,
|
||||||
|
menuActive: false,
|
||||||
};
|
};
|
||||||
let loginData = JSON.parse(window.localStorage.getItem('login_data'))
|
let loginData = JSON.parse(window.localStorage.getItem('login_data'))
|
||||||
if (loginData) {
|
if (loginData) {
|
||||||
|
@ -79,21 +80,19 @@ export default new Vuex.Store({
|
||||||
'Authorization': 'Bearer ' + this.state.access_token
|
'Authorization': 'Bearer ' + this.state.access_token
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
state.eventSource.addEventListener('open', evt => {
|
// state.eventSource.addEventListener('open', evt => {
|
||||||
// eslint-disable-next-line
|
// // eslint-disable-next-line
|
||||||
console.log(evt)
|
// console.log(evt)
|
||||||
})
|
// })
|
||||||
state.eventSource.addEventListener('ping', evt => {
|
// state.eventSource.addEventListener('ping', evt => {
|
||||||
// eslint-disable-next-line
|
// // eslint-disable-next-line
|
||||||
console.log(evt)
|
// console.log(evt)
|
||||||
})
|
// })
|
||||||
state.eventSource.addEventListener('message', evt => {
|
// state.eventSource.addEventListener('message', evt => {
|
||||||
// eslint-disable-next-line
|
// // eslint-disable-next-line
|
||||||
console.log(evt)
|
// console.log(evt)
|
||||||
})
|
// })
|
||||||
state.eventSource.addEventListener('error', evt => {
|
state.eventSource.addEventListener('error', evt => {
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log(evt)
|
|
||||||
if (evt.message === "network error") {
|
if (evt.message === "network error") {
|
||||||
state.eventSource.close()
|
state.eventSource.close()
|
||||||
}
|
}
|
||||||
|
@ -111,8 +110,6 @@ export default new Vuex.Store({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
state.eventSource.addEventListener('new item in channel', evt => {
|
state.eventSource.addEventListener('new item in channel', evt => {
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log(evt)
|
|
||||||
let msg = JSON.parse(evt.data)
|
let msg = JSON.parse(evt.data)
|
||||||
let channel = _.find(state.channels, item => item.uid === msg.uid)
|
let channel = _.find(state.channels, item => item.uid === msg.uid)
|
||||||
if (channel) {
|
if (channel) {
|
||||||
|
@ -121,8 +118,6 @@ export default new Vuex.Store({
|
||||||
})
|
})
|
||||||
|
|
||||||
state.eventSource.addEventListener('new channel', evt => {
|
state.eventSource.addEventListener('new channel', evt => {
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log(evt)
|
|
||||||
let msg = JSON.parse(evt.data)
|
let msg = JSON.parse(evt.data)
|
||||||
let channel = _.find(state.channels, it => it.uid === msg.channel.uid)
|
let channel = _.find(state.channels, it => it.uid === msg.channel.uid)
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
|
@ -131,8 +126,6 @@ export default new Vuex.Store({
|
||||||
})
|
})
|
||||||
|
|
||||||
state.eventSource.addEventListener('update channel', evt => {
|
state.eventSource.addEventListener('update channel', evt => {
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log(evt)
|
|
||||||
let msg = JSON.parse(evt.data)
|
let msg = JSON.parse(evt.data)
|
||||||
let channel = _.find(state.channels, it => it.uid === msg.channel.uid)
|
let channel = _.find(state.channels, it => it.uid === msg.channel.uid)
|
||||||
if (channel) {
|
if (channel) {
|
||||||
|
@ -141,10 +134,8 @@ export default new Vuex.Store({
|
||||||
})
|
})
|
||||||
|
|
||||||
state.eventSource.addEventListener('delete channel', evt => {
|
state.eventSource.addEventListener('delete channel', evt => {
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log(evt)
|
|
||||||
let msg = JSON.parse(evt.data)
|
let msg = JSON.parse(evt.data)
|
||||||
state.channels = _.remove(state.channels, it => it.uid === msg.uid)
|
state.channels = _.filter(state.channels, it => it.uid !== msg.uid)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
newSearchResults(state, items) {
|
newSearchResults(state, items) {
|
||||||
|
@ -156,6 +147,9 @@ export default new Vuex.Store({
|
||||||
},
|
},
|
||||||
closeDebugPopup(state) {
|
closeDebugPopup(state) {
|
||||||
state.debugVisible = false
|
state.debugVisible = false
|
||||||
|
},
|
||||||
|
activateMenu(state) {
|
||||||
|
state.menuActive = !state.menuActive
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -175,6 +169,9 @@ export default new Vuex.Store({
|
||||||
commit('clearTimeline', {channel: channel})
|
commit('clearTimeline', {channel: channel})
|
||||||
},
|
},
|
||||||
fetchTimeline({commit}, channel) {
|
fetchTimeline({commit}, channel) {
|
||||||
|
if (!channel.uid) {
|
||||||
|
channel.uid = 'home';
|
||||||
|
}
|
||||||
let url = this.state.microsubEndpoint + '?action=timeline&channel=' + channel.uid
|
let url = this.state.microsubEndpoint + '?action=timeline&channel=' + channel.uid
|
||||||
if (channel.after) {
|
if (channel.after) {
|
||||||
url += '&after=' + channel.after;
|
url += '&after=' + channel.after;
|
||||||
|
@ -261,14 +258,22 @@ export default new Vuex.Store({
|
||||||
commit('setSearchPopupState', false)
|
commit('setSearchPopupState', false)
|
||||||
},
|
},
|
||||||
startQuery({state, commit}, query) {
|
startQuery({state, commit}, query) {
|
||||||
let channel = 'global'
|
let channel
|
||||||
if (state.channel !== null && state.channel.uid !== null && state.channel.uid !== 'home') {
|
if (query.channel) {
|
||||||
channel = state.channel.uid
|
if (query.channel === 'global') {
|
||||||
|
channel = 'global'
|
||||||
|
} else if (query.channel === 'channel') {
|
||||||
|
if (state.channel !== null && state.channel.uid !== null) {
|
||||||
|
channel = state.channel.uid
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel = 'global'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const url = new URL(this.state.microsubEndpoint)
|
const url = new URL(this.state.microsubEndpoint)
|
||||||
url.searchParams.set('action', 'search')
|
url.searchParams.set('action', 'search')
|
||||||
url.searchParams.set('channel', channel)
|
url.searchParams.set('channel', channel)
|
||||||
url.searchParams.set('query', query)
|
url.searchParams.set('query', query.query)
|
||||||
return fetch(url.toString(), {
|
return fetch(url.toString(), {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer ' + this.state.access_token
|
'Authorization': 'Bearer ' + this.state.access_token
|
||||||
|
@ -318,7 +323,7 @@ export default new Vuex.Store({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
startEventListening({commit}, url) {
|
startEventListening({commit}, url) {
|
||||||
commit('createEventSource', url)
|
return commit('createEventSource', url)
|
||||||
},
|
},
|
||||||
openDebug({commit}, item) {
|
openDebug({commit}, item) {
|
||||||
return commit('openDebugPopup', item)
|
return commit('openDebugPopup', item)
|
||||||
|
@ -326,5 +331,8 @@ export default new Vuex.Store({
|
||||||
closeDebug({commit}) {
|
closeDebug({commit}) {
|
||||||
return commit('closeDebugPopup')
|
return commit('closeDebugPopup')
|
||||||
},
|
},
|
||||||
|
toggleMenu({commit}) {
|
||||||
|
return commit('activateMenu')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="column" style="padding-top: 20px">
|
<div class="column" style="padding-top: 20px">
|
||||||
<button class="channels-toggle button" type="button" @click="showChannels">Channels</button>
|
<button class="channels-toggle button" type="button" @click="showChannels">Channels</button>
|
||||||
|
|
||||||
<Channels :class="channelsClass" :channels="this.$store.state.channels">
|
<Channels :class="channelsClass" :channels="this.channels">
|
||||||
<div slot-scope="{ channel }">
|
<div slot-scope="{ channel }">
|
||||||
<Channel :channel="channel" @channel-selected="selectChannel"></Channel>
|
<Channel :channel="channel" @channel-selected="selectChannel"></Channel>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,14 +11,14 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="timeline column is-three-fifths">
|
<div class="timeline column is-three-fifths">
|
||||||
<div class="level">
|
<div class="level is-mobile">
|
||||||
<div class="level-left">
|
<div class="level-left">
|
||||||
<h1 class="title is-5">{{ channel.name }}</h1>
|
<h1 class="title is-5">{{ channel.name }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="level-right timeline-buttons">
|
<div class="level-right timeline-buttons">
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<button class="button" @click.prevent="openPost">New Post</button>
|
<button class="button is-small" @click.prevent="openPost">New Post</button>
|
||||||
<button class="button" @click.prevent="openFeedFollower('')">Add feed</button>
|
<button class="button is-small" @click.prevent="openFeedFollower('')">Add feed</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,6 +80,9 @@
|
||||||
channel() {
|
channel() {
|
||||||
return this.$store.state.channel
|
return this.$store.state.channel
|
||||||
},
|
},
|
||||||
|
channels() {
|
||||||
|
return this.$store.state.channels
|
||||||
|
},
|
||||||
channelsClass () {
|
channelsClass () {
|
||||||
return {
|
return {
|
||||||
'channels-open': this.channelsVisible,
|
'channels-open': this.channelsVisible,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user