aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/conversation-page/conversation-page.js8
-rw-r--r--src/components/conversation-page/conversation-page.vue2
-rw-r--r--src/components/conversation/conversation.js51
-rw-r--r--src/components/login_form/login_form.vue5
-rw-r--r--src/components/password_reset/password_reset.js62
-rw-r--r--src/components/password_reset/password_reset.vue116
-rw-r--r--src/components/timeline/timeline.vue4
-rw-r--r--src/components/who_to_follow/who_to_follow.js2
-rw-r--r--src/components/who_to_follow_panel/who_to_follow_panel.js2
9 files changed, 220 insertions, 32 deletions
diff --git a/src/components/conversation-page/conversation-page.js b/src/components/conversation-page/conversation-page.js
index 1da70ce9..8f996be1 100644
--- a/src/components/conversation-page/conversation-page.js
+++ b/src/components/conversation-page/conversation-page.js
@@ -5,12 +5,8 @@ const conversationPage = {
Conversation
},
computed: {
- statusoid () {
- const id = this.$route.params.id
- const statuses = this.$store.state.statuses.allStatusesObject
- const status = statuses[id]
-
- return status
+ statusId () {
+ return this.$route.params.id
}
}
}
diff --git a/src/components/conversation-page/conversation-page.vue b/src/components/conversation-page/conversation-page.vue
index 532f785c..8cc0a55f 100644
--- a/src/components/conversation-page/conversation-page.vue
+++ b/src/components/conversation-page/conversation-page.vue
@@ -2,7 +2,7 @@
<conversation
:collapsable="false"
is-page="true"
- :statusoid="statusoid"
+ :status-id="statusId"
/>
</template>
diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 49fa8612..10dd8eb0 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -1,4 +1,4 @@
-import { reduce, filter, findIndex, clone } from 'lodash'
+import { reduce, filter, findIndex, clone, get } from 'lodash'
import Status from '../status/status.vue'
const sortById = (a, b) => {
@@ -39,7 +39,7 @@ const conversation = {
}
},
props: [
- 'statusoid',
+ 'statusId',
'collapsable',
'isPage',
'pinnedStatusIdsObject'
@@ -51,21 +51,17 @@ const conversation = {
},
computed: {
status () {
- return this.statusoid
+ return this.$store.state.statuses.allStatusesObject[this.statusId]
},
- statusId () {
- if (this.statusoid.retweeted_status) {
- return this.statusoid.retweeted_status.id
+ originalStatusId () {
+ if (this.status.retweeted_status) {
+ return this.status.retweeted_status.id
} else {
- return this.statusoid.id
+ return this.statusId
}
},
conversationId () {
- if (this.statusoid.retweeted_status) {
- return this.statusoid.retweeted_status.statusnet_conversation_id
- } else {
- return this.statusoid.statusnet_conversation_id
- }
+ return this.getConversationId(this.statusId)
},
conversation () {
if (!this.status) {
@@ -77,7 +73,7 @@ const conversation = {
}
const conversation = clone(this.$store.state.statuses.conversationsObject[this.conversationId])
- const statusIndex = findIndex(conversation, { id: this.statusId })
+ const statusIndex = findIndex(conversation, { id: this.originalStatusId })
if (statusIndex !== -1) {
conversation[statusIndex] = this.status
}
@@ -110,7 +106,15 @@ const conversation = {
Status
},
watch: {
- status: 'fetchConversation',
+ statusId (newVal, oldVal) {
+ const newConversationId = this.getConversationId(newVal)
+ const oldConversationId = this.getConversationId(oldVal)
+ if (newConversationId && oldConversationId && newConversationId === oldConversationId) {
+ this.setHighlight(this.originalStatusId)
+ } else {
+ this.fetchConversation()
+ }
+ },
expanded (value) {
if (value) {
this.fetchConversation()
@@ -120,24 +124,25 @@ const conversation = {
methods: {
fetchConversation () {
if (this.status) {
- this.$store.state.api.backendInteractor.fetchConversation({ id: this.status.id })
+ this.$store.state.api.backendInteractor.fetchConversation({ id: this.statusId })
.then(({ ancestors, descendants }) => {
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
this.$store.dispatch('addNewStatuses', { statuses: descendants })
+ this.setHighlight(this.originalStatusId)
})
- .then(() => this.setHighlight(this.statusId))
} else {
- const id = this.$route.params.id
- this.$store.state.api.backendInteractor.fetchStatus({ id })
- .then((status) => this.$store.dispatch('addNewStatuses', { statuses: [status] }))
- .then(() => this.fetchConversation())
+ this.$store.state.api.backendInteractor.fetchStatus({ id: this.statusId })
+ .then((status) => {
+ this.$store.dispatch('addNewStatuses', { statuses: [status] })
+ this.fetchConversation()
+ })
}
},
getReplies (id) {
return this.replies[id] || []
},
focused (id) {
- return (this.isExpanded) && id === this.status.id
+ return (this.isExpanded) && id === this.statusId
},
setHighlight (id) {
if (!id) return
@@ -149,6 +154,10 @@ const conversation = {
},
toggleExpanded () {
this.expanded = !this.expanded
+ },
+ getConversationId (statusId) {
+ const status = this.$store.state.statuses.allStatusesObject[statusId]
+ return get(status, 'retweeted_status.statusnet_conversation_id', get(status, 'statusnet_conversation_id'))
}
}
}
diff --git a/src/components/login_form/login_form.vue b/src/components/login_form/login_form.vue
index 3ec7fe0c..b4fdcefb 100644
--- a/src/components/login_form/login_form.vue
+++ b/src/components/login_form/login_form.vue
@@ -33,6 +33,11 @@
type="password"
>
</div>
+ <div class="form-group">
+ <router-link :to="{name: 'password-reset'}">
+ {{ $t('password_reset.forgot_password') }}
+ </router-link>
+ </div>
</template>
<div
diff --git a/src/components/password_reset/password_reset.js b/src/components/password_reset/password_reset.js
new file mode 100644
index 00000000..fa71e07a
--- /dev/null
+++ b/src/components/password_reset/password_reset.js
@@ -0,0 +1,62 @@
+import { mapState } from 'vuex'
+import passwordResetApi from '../../services/new_api/password_reset.js'
+
+const passwordReset = {
+ data: () => ({
+ user: {
+ email: ''
+ },
+ isPending: false,
+ success: false,
+ throttled: false,
+ error: null
+ }),
+ computed: {
+ ...mapState({
+ signedIn: (state) => !!state.users.currentUser,
+ instance: state => state.instance
+ }),
+ mailerEnabled () {
+ return this.instance.mailerEnabled
+ }
+ },
+ created () {
+ if (this.signedIn) {
+ this.$router.push({ name: 'root' })
+ }
+ },
+ methods: {
+ dismissError () {
+ this.error = null
+ },
+ submit () {
+ this.isPending = true
+ const email = this.user.email
+ const instance = this.instance.server
+
+ passwordResetApi({ instance, email }).then(({ status }) => {
+ this.isPending = false
+ this.user.email = ''
+
+ if (status === 204) {
+ this.success = true
+ this.error = null
+ } else if (status === 404 || status === 400) {
+ this.error = this.$t('password_reset.not_found')
+ this.$nextTick(() => {
+ this.$refs.email.focus()
+ })
+ } else if (status === 429) {
+ this.throttled = true
+ this.error = this.$t('password_reset.too_many_requests')
+ }
+ }).catch(() => {
+ this.isPending = false
+ this.user.email = ''
+ this.error = this.$t('general.generic_error')
+ })
+ }
+ }
+}
+
+export default passwordReset
diff --git a/src/components/password_reset/password_reset.vue b/src/components/password_reset/password_reset.vue
new file mode 100644
index 00000000..00474e95
--- /dev/null
+++ b/src/components/password_reset/password_reset.vue
@@ -0,0 +1,116 @@
+<template>
+ <div class="settings panel panel-default">
+ <div class="panel-heading">
+ {{ $t('password_reset.password_reset') }}
+ </div>
+ <div class="panel-body">
+ <form
+ class="password-reset-form"
+ @submit.prevent="submit"
+ >
+ <div class="container">
+ <div v-if="!mailerEnabled">
+ <p>
+ {{ $t('password_reset.password_reset_disabled') }}
+ </p>
+ </div>
+ <div v-else-if="success || throttled">
+ <p v-if="success">
+ {{ $t('password_reset.check_email') }}
+ </p>
+ <div class="form-group text-center">
+ <router-link :to="{name: 'root'}">
+ {{ $t('password_reset.return_home') }}
+ </router-link>
+ </div>
+ </div>
+ <div v-else>
+ <p>
+ {{ $t('password_reset.instruction') }}
+ </p>
+ <div class="form-group">
+ <input
+ ref="email"
+ v-model="user.email"
+ :disabled="isPending"
+ :placeholder="$t('password_reset.placeholder')"
+ class="form-control"
+ type="input"
+ >
+ </div>
+ <div class="form-group">
+ <button
+ :disabled="isPending"
+ type="submit"
+ class="btn btn-default btn-block"
+ >
+ {{ $t('general.submit') }}
+ </button>
+ </div>
+ </div>
+ <p
+ v-if="error"
+ class="alert error notice-dismissible"
+ >
+ <span>{{ error }}</span>
+ <a
+ class="button-icon dismiss"
+ @click.prevent="dismissError()"
+ >
+ <i class="icon-cancel" />
+ </a>
+ </p>
+ </div>
+ </form>
+ </div>
+ </div>
+</template>
+
+<script src="./password_reset.js"></script>
+<style lang="scss">
+@import '../../_variables.scss';
+
+.password-reset-form {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 0.6em;
+
+ .container {
+ display: flex;
+ flex: 1 0;
+ flex-direction: column;
+ margin-top: 0.6em;
+ max-width: 18rem;
+ }
+
+ .form-group {
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 1em;
+ padding: 0.3em 0.0em 0.3em;
+ line-height: 24px;
+ }
+
+ .error {
+ text-align: center;
+ animation-name: shakeError;
+ animation-duration: 0.4s;
+ animation-timing-function: ease-in-out;
+ }
+
+ .alert {
+ padding: 0.5em;
+ margin: 0.3em 0.0em 1em;
+ }
+
+ .notice-dismissible {
+ padding-right: 2rem;
+ }
+
+ .icon-cancel {
+ cursor: pointer;
+ }
+}
+
+</style>
diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index 4ad51714..ba66e6da 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -33,7 +33,7 @@
v-if="timeline.statusesObject[statusId]"
:key="statusId + '-pinned'"
class="status-fadein"
- :statusoid="timeline.statusesObject[statusId]"
+ :status-id="statusId"
:collapsable="true"
:pinned-status-ids-object="pinnedStatusIdsObject"
/>
@@ -43,7 +43,7 @@
v-if="!excludedStatusIdsObject[status.id]"
:key="status.id"
class="status-fadein"
- :statusoid="status"
+ :status-id="status.id"
:collapsable="true"
/>
</template>
diff --git a/src/components/who_to_follow/who_to_follow.js b/src/components/who_to_follow/who_to_follow.js
index 8fab6c4d..1aa3a4cd 100644
--- a/src/components/who_to_follow/who_to_follow.js
+++ b/src/components/who_to_follow/who_to_follow.js
@@ -26,7 +26,7 @@ const WhoToFollow = {
}
this.users.push(user)
- this.$store.state.api.backendInteractor.externalProfile(user.screen_name)
+ this.$store.state.api.backendInteractor.fetchUser({ id: user.screen_name })
.then((externalUser) => {
if (!externalUser.error) {
this.$store.commit('addNewUsers', [externalUser])
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.js b/src/components/who_to_follow_panel/who_to_follow_panel.js
index 7d01678b..dcb56106 100644
--- a/src/components/who_to_follow_panel/who_to_follow_panel.js
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.js
@@ -13,7 +13,7 @@ function showWhoToFollow (panel, reply) {
toFollow.img = img
toFollow.name = name
- panel.$store.state.api.backendInteractor.externalProfile(name)
+ panel.$store.state.api.backendInteractor.fetchUser({ id: name })
.then((externalUser) => {
if (!externalUser.error) {
panel.$store.commit('addNewUsers', [externalUser])