Skip to content

Commit

Permalink
Merge pull request #883 from SoftwareEngineeringDaily/feat/write-topi…
Browse files Browse the repository at this point in the history
…c-handling

feat(): improve write topic claim ux - fixes #879
  • Loading branch information
sterlingrules authored Jun 17, 2020
2 parents a971e91 + 76794da commit 3f5b855
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 69 deletions.
20 changes: 20 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,26 @@ a
.fade-enter, .fade-leave-active
opacity 0
.toasted-container .bubble
padding 6px 20px
font-weight 700
.toasted-container .toasted .action
box-sizing border-box
margin-left 14px
padding 4px 12px
font-size 0.75em
color #222
background-color #fff
border 2px solid #fff
border-radius 36px
&:hover
color #fff
text-decoration none
background-color transparent
border 2px solid #fff
@media (max-width 660px)
.header .inner-mobile
flex-direction column
Expand Down
19 changes: 15 additions & 4 deletions src/components/topic/TopicsAutoComplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
:hide-selected="true"
@search-change="onSearch">

<span slot="noOptions"></span>
<span slot="noResult">No topics found.</span>

</multiselect>
Expand All @@ -28,6 +29,7 @@
<script>
import Multiselect from 'vue-multiselect'
import { mapState, mapActions } from 'vuex'
import { delay } from '@/utils/post.utils'
export default {
name: 'topics-auto-complete',
Expand Down Expand Up @@ -86,10 +88,16 @@ export default {
'getSearchedTopics',
]),
async onSearch (query) {
this.isLoading = true
await this.getSearchedTopics(query)
this.isLoading = false
async onSearch (query = '') {
if (!query || (query && query.length < 2)) {
return
}
delay(async () => {
this.isLoading = true
await this.getSearchedTopics(query)
this.isLoading = false
}, 300)
},
limitText (count) {
Expand Down Expand Up @@ -142,6 +150,9 @@ export default {
&:after
color #fff
>>> .multiselect__content li:last-child
display none
>>> .multiselect__option.multiselect__option--highlight
&,
&:after
Expand Down
1 change: 1 addition & 0 deletions src/views/topic/content/TopicPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ export default {
margin-top 10px
padding 4px 12px
color #a591ff
background-color transparent
border 1px solid #a591ff
border-radius 18px
Expand Down
161 changes: 97 additions & 64 deletions src/views/write/WriteInfoView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,75 +4,72 @@
:canSuggest="true">

<div class="write-info-view">
<div v-if="!me || !me._id" class="display-content">
You need to login first.
</div>

<template v-else>

<div class="list">
<div class="form">
<div class="list-input">
<topics-auto-complete
v-model="newTopic"
placeholder="Write about an existing topic"
:multiple="false" />
<button
:disabled="!newTopic"
@click="onClickTopic(newTopic)">
<div class="list">
<div class="form">
<div class="list-input">
<topics-auto-complete
v-model="newTopic"
placeholder="Search an existing topic to write about"
:multiple="false" />
<button
:disabled="!newTopic"
@click="onClickTopic(newTopic)">
<span v-if="hasMaintainers(newTopic)">
View
</span>
<span v-else>
Write
</button>
</div>
</span>
</button>
</div>
</div>

<spinner :show="loading"/>
<spinner :show="loading"/>

<strong class="list-label">Suggested topics</strong>
<strong class="list-label">Suggested topics</strong>

<div v-if="!loading" class="flex">
<button
v-for="topic in topics"
:key="topic._id"
class="list-item topic-select"
@click="onClickTopic(topic)">
{{topic.name}}
</button>
<div v-if="!loading" class="flex">
<button
v-for="topic in topics"
:key="topic._id"
class="list-item topic-select"
@click="onClickTopic(topic)">
{{topic.name}}
</button>

<topic-create />
</div>
<topic-create />
</div>
</div>

<div class="list">
<h2 class="list-headline">Questions</h2>
<div
v-for="question in unansweredQuestions"
:key="question._id">

<div class="topicpage-header">
<div class="post-topics">
<router-link :to="`/topic/${question.topic.slug}`" class="topics">
{{question.topic.name}}
</router-link>
</div>
<div class="list">
<h2 class="list-headline">Questions</h2>
<div
v-for="question in unansweredQuestions"
:key="question._id">

<div class="topicpage-header">
<div class="post-topics">
<router-link :to="`/topic/${question.topic.slug}`" class="topics">
{{question.topic.name}}
</router-link>
</div>
</div>

<question
:topicSlug="question.topic.slug"
:answerLimit="0"
:question="question"
:canAnswer="false" />
<question
:topicSlug="question.topic.slug"
:answerLimit="0"
:question="question"
:canAnswer="false" />

</div>
</div>

</template>
</div>
</div>

</write-request>
</template>

<script>
import { mapActions, mapState } from 'vuex'
import { mapActions, mapState, mapGetters } from 'vuex'
import Question from '@/components/qa/Question'
import { TopicsAutoComplete, TopicCreate } from '@/components/topic'
import WriteRequest from '@/views/write/WriteRequest'
Expand Down Expand Up @@ -102,6 +99,10 @@ export default {
},
computed: {
...mapGetters([
'isLoggedIn'
]),
...mapState({
me (state) {
return state.me
Expand All @@ -117,27 +118,60 @@ export default {
...mapActions([
'getTopTopics',
'getUnansweredQuestions',
'setMaintainerInterest',
'setMaintainer',
]),
onCancelSelection() {
this.newTopic = null
},
loadTopics() {
this.loading = true
this.getTopTopics(5).then((data) => {
this.getUnansweredQuestions(10)
this.topics = data
}).catch((e) => {
this.$toasted.error((e.response) ? e.response.data : e, { duration : 0 })
this.$toasted.error((e.response) ? e.response.data : e, { duration: 0 })
}).finally(() => {
this.loading = false
})
},
hasMaintainers (topic) {
return (
topic &&
topic.maintainers &&
topic.maintainers.length > 0
)
},
onCancelSelection() {
this.newTopic = null
},
onClickTopic(topic) {
this.selectedTopic = topic.name
if (this.hasMaintainers(topic)) {
return this.$router.history.push(`/topic/${topic.slug}`)
}
if (!this.isLoggedIn) {
return this.$toasted.success('Please, login or sign up first.', {
action: [
{
text: 'Sign In',
onClick : (e, toastObject) => {
this.$router.history.push('/login');
toastObject.goAway(0);
},
},
{
text: 'Close',
onClick : (e, toastObject) => {
toastObject.goAway(0);
},
},
],
duration: 0,
})
}
this.selectedTopic = topic.slug
this.$nextTick(() => {
this.requestTopicOwnership()
})
Expand All @@ -147,17 +181,16 @@ export default {
this.saving = true
const data = {
topicName: this.selectedTopic,
userName: this.me.name,
userEmail: this.me.email,
topicSlug: this.selectedTopic,
event: 'selfAssign'
}
try {
await this.setMaintainerInterest(data)
this.$toasted.success('Great! We will be in touch with you.', { duration : 8000 })
await this.setMaintainer(data)
this.$router.history.push(`/topic/${this.selectedTopic}/edit`)
}
catch (e) {
this.$toasted.error((e.response) ? e.response.data : e, { duration : 0 })
this.$toasted.error((e.message) ? e.message : e, { duration: 0 })
}
if (typeof this.onCancelSelection === 'function') {
Expand Down
3 changes: 2 additions & 1 deletion src/views/write/WriteRequest.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,15 @@ export default {
&:hover
color #222
text-decoration underline
.select
margin-bottom 20px
display inline-block
padding 4px 12px
font-size 14px
font-weight 700
color #a591ff
background-color transparent
border 2px solid #a591ff
border-radius 18px
Expand Down

0 comments on commit 3f5b855

Please sign in to comment.