kopia lustrzana https://github.com/nextcloud/social
				
				
				
			Merge pull request #625 from nextcloud/feature/605/notificationsTimeline
[WIP] Notifications timeline (frontend)pull/732/head
						commit
						fd069f3e60
					
				|  | @ -2,6 +2,7 @@ | |||
| @include icon-black-white('emoji', 'social', 1); | ||||
| @include icon-black-white('boost', 'social', 1); | ||||
| @include icon-black-white('upload', 'actions', 1, true); | ||||
| @include icon-black-white('notifications', 'social', 1); | ||||
| 
 | ||||
| .icon-boosted { | ||||
|   @include icon-color('boost', 'social', '#0082c9', 1); | ||||
|  |  | |||
|  | @ -0,0 +1,4 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16"> | ||||
|  <path d="m8 2c-0.5523 0-1 0.4477-1 1 0 0.0472 0.021 0.0873 0.0273 0.1328-1.7366 0.4362-3.0273 1.9953-3.0273 3.8672v2l-1 1v1h10v-1l-1-1v-2c0-1.8719-1.291-3.431-3.0273-3.8672 0.0063-0.0455 0.0273-0.0856 0.0273-0.1328 0-0.5523-0.4477-1-1-1zm-2 10c0 1.1046 0.8954 2 2 2s2-0.8954 2-2z" fill="#000"/> | ||||
| </svg> | ||||
| Po Szerokość: | Wysokość: | Rozmiar: 456 B | 
|  | @ -122,6 +122,8 @@ trait TDetails { | |||
| 	public function addDetail(string $detail, string $value) { | ||||
| 		if (!array_key_exists($detail, $this->details) || !is_array($this->details[$detail])) { | ||||
| 			$this->details[$detail] = []; | ||||
| 		} else if (in_array($value, $this->details[$detail])) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		$this->details[$detail][] = $value; | ||||
|  |  | |||
							
								
								
									
										20
									
								
								src/App.vue
								
								
								
								
							
							
						
						
									
										20
									
								
								src/App.vue
								
								
								
								
							|  | @ -136,16 +136,16 @@ export default { | |||
| 					icon: 'icon-comment', | ||||
| 					text: t('social', 'Direct messages') | ||||
| 				}, | ||||
| 				// { | ||||
| 				// 	id: 'social-notifications', | ||||
| 				// 	classes: [], | ||||
| 				// 	router: { | ||||
| 				// 		name: 'timeline', | ||||
| 				// 		params: { type: 'notifications' } | ||||
| 				// 	}, | ||||
| 				// 	icon: 'icon-comment', | ||||
| 				// 	text: t('social', 'Notifications') | ||||
| 				// }, | ||||
| 				{ | ||||
| 					id: 'social-notifications', | ||||
| 					classes: [], | ||||
| 					router: { | ||||
| 						name: 'timeline', | ||||
| 						params: { type: 'notifications' } | ||||
| 					}, | ||||
| 					icon: 'icon-notifications', | ||||
| 					text: t('social', 'Notifications') | ||||
| 				}, | ||||
| 				{ | ||||
| 					id: 'social-account', | ||||
| 					classes: [], | ||||
|  |  | |||
|  | @ -19,20 +19,23 @@ | |||
| 			</a> | ||||
| 			{{ boosted }} | ||||
| 		</div> | ||||
| 		<timeline-post v-if="(item.type === 'Note' || item.type === 'Announce')" :item="entryContent" :parent-announce="isBoost" /> | ||||
| 		<user-entry v-if="item.type === 'SocialAppNotificationUser'" :key="user.id" :item="user" /> | ||||
| 		<timeline-post | ||||
| 			v-if="item.type === 'SocialAppNotification' && item.details.post" | ||||
| 			:item="item.details.post" /> | ||||
| 		<timeline-post | ||||
| 			v-else | ||||
| 			:item="entryContent" | ||||
| 			:parent-announce="isBoost" /> | ||||
| 	</div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import TimelinePost from './TimelinePost.vue' | ||||
| import UserEntry from './UserEntry.vue' | ||||
| 
 | ||||
| export default { | ||||
| 	name: 'TimelineEntry', | ||||
| 	components: { | ||||
| 		TimelinePost, | ||||
| 		UserEntry | ||||
| 		TimelinePost | ||||
| 	}, | ||||
| 	props: { | ||||
| 		item: { type: Object, default: () => {} } | ||||
|  | @ -59,11 +62,34 @@ export default { | |||
| 			return t('social', 'boosted') | ||||
| 		}, | ||||
| 		actionSummary() { | ||||
| 
 | ||||
| 			let summary = this.item.summary | ||||
| 			for (var key in this.item.details) { | ||||
| 
 | ||||
| 				let keyword = '{' + key + '}' | ||||
| 				summary = summary.replace(keyword, JSON.stringify(this.item.details[key])) | ||||
| 				if (typeof this.item.details[key] !== 'string' && this.item.details[key].length > 1) { | ||||
| 
 | ||||
| 					let concatination = '' | ||||
| 					for (var stringKey in this.item.details[key]) { | ||||
| 
 | ||||
| 						if (this.item.details[key].length > 3 && stringKey === '3') { | ||||
| 							// ellipses the actors' list to 3 actors when it's big | ||||
| 							concatination = concatination.substring(0, concatination.length - 2) | ||||
| 							concatination += ' and ' + (this.item.details[key].length - 3).toString() + ' other(s), ' | ||||
| 							break | ||||
| 						} else { | ||||
| 							concatination += this.item.details[key][stringKey] + ', ' | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					concatination = concatination.substring(0, concatination.length - 2) | ||||
| 					summary = summary.replace(keyword, concatination) | ||||
| 
 | ||||
| 				} else { | ||||
| 					summary = summary.replace(keyword, this.item.details[key]) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			return summary | ||||
| 		} | ||||
| 	}, | ||||
|  |  | |||
|  | @ -92,15 +92,24 @@ export default { | |||
| 					title: t('social', 'No local posts found'), | ||||
| 					description: t('social', 'Posts from other people on this instance will show up here') | ||||
| 				}, | ||||
| 				notifications: { | ||||
| 					image: 'img/undraw/notifications.svg', | ||||
| 					title: t('social', 'No notifications found'), | ||||
| 					description: t('social', 'You haven\'t receive any notifications yet') | ||||
| 				}, | ||||
| 				federated: { | ||||
| 					image: 'img/undraw/global.svg', | ||||
| 					title: t('social', 'No global posts found'), | ||||
| 					description: t('social', 'Posts from federated instances will show up here') | ||||
| 				}, | ||||
| 				liked: { | ||||
| 					image: 'img/undraw/profile.svg', | ||||
| 					image: 'img/undraw/likes.svg', | ||||
| 					title: t('social', 'No liked posts found') | ||||
| 				}, | ||||
| 				profile: { | ||||
| 					image: 'img/undraw/profile.svg', | ||||
| 					title: t('social', 'You haven\'t tooted yet') | ||||
| 				}, | ||||
| 				tags: { | ||||
| 					image: 'img/undraw/profile.svg', | ||||
| 					title: t('social', 'No posts found for this tag') | ||||
|  | @ -110,12 +119,12 @@ export default { | |||
| 	}, | ||||
| 	computed: { | ||||
| 		emptyContentData() { | ||||
| 			if (typeof this.emptyContent[this.$route.name] !== 'undefined') { | ||||
| 				return this.emptyContent[this.$route.name] | ||||
| 			} | ||||
| 			if (typeof this.emptyContent[this.$route.params.type] !== 'undefined') { | ||||
| 				return this.emptyContent[this.$route.params.type] | ||||
| 			} | ||||
| 			if (typeof this.emptyContent[this.$route.name] !== 'undefined') { | ||||
| 				return this.$route.name === 'timeline' ? this.emptyContent['default'] : this.emptyContent[this.$route.name] | ||||
| 			} | ||||
| 			return this.emptyContent.default | ||||
| 		}, | ||||
| 		timeline: function() { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| 	<div class="entry-content"> | ||||
| 		<div v-if="item.actor_info" class="post-avatar"> | ||||
| 			<avatar v-if="item.local" :size="32" :user="item.actor_info.preferredUsername" | ||||
| 			<avatar v-if="item.local && item.type!=='SocialAppNotification'" :size="32" :user="item.actor_info.preferredUsername" | ||||
| 				:display-name="item.actor_info.account" :disable-tooltip="true" /> | ||||
| 			<avatar v-else :size="32" :url="avatarUrl" | ||||
| 				:disable-tooltip="true" /> | ||||
|  | @ -9,7 +9,10 @@ | |||
| 		<div class="post-content"> | ||||
| 			<div class="post-header"> | ||||
| 				<div class="post-author-wrapper"> | ||||
| 					<router-link v-if="item.actor_info" :to="{ name: 'profile', params: { account: item.local ? item.actor_info.preferredUsername : item.actor_info.account }}"> | ||||
| 					<router-link v-if="item.actor_info" | ||||
| 						:to="{ name: 'profile', | ||||
| 							params: { account: (item.local && item.type!=='SocialAppNotification') ? item.actor_info.preferredUsername : item.actor_info.account } | ||||
| 						}"> | ||||
| 						<span class="post-author"> | ||||
| 							{{ userDisplayName(item.actor_info) }} | ||||
| 						</span> | ||||
|  | @ -28,11 +31,13 @@ | |||
| 				</div> | ||||
| 			</div> | ||||
| 			<!-- eslint-disable-next-line vue/no-v-html --> | ||||
| 			<div class="post-message" v-html="formatedMessage" /> | ||||
| 			<div v-if="item.content" class="post-message" v-html="formatedMessage" /> | ||||
| 			<!-- eslint-disable-next-line vue/no-v-html --> | ||||
| 			<div v-else class="post-message" v-html="item.actor_info.summary" /> | ||||
| 			<div v-if="hasAttachments" class="post-attachments"> | ||||
| 				<post-attachment :attachments="item.attachment" /> | ||||
| 			</div> | ||||
| 			<div v-click-outside="hidePopoverMenu" class="post-actions"> | ||||
| 			<div v-if="this.$route.params.type!=='notifications'" v-click-outside="hidePopoverMenu" class="post-actions"> | ||||
| 				<a v-tooltip.bottom="t('social', 'Reply')" class="icon-reply" @click.prevent="reply" /> | ||||
| 				<a v-if="item.actor_info.account !== cloudId" v-tooltip.bottom="t('social', 'Boost')" | ||||
| 					:class="(isBoosted) ? 'icon-boosted' : 'icon-boost'" | ||||
|  |  | |||
|  | @ -92,12 +92,6 @@ export default { | |||
| } | ||||
| </script> | ||||
| <style scoped> | ||||
| 	.user-entry { | ||||
| 		width: 100%; | ||||
| 		padding: 20px; | ||||
| 		margin-bottom: 10px; | ||||
| 	} | ||||
| 
 | ||||
| 	.user-avatar { | ||||
| 		margin: 5px; | ||||
| 		margin-right: 10px; | ||||
|  |  | |||
|  | @ -34,6 +34,11 @@ | |||
| 		display: flex; | ||||
| 		flex-wrap: wrap; | ||||
| 	} | ||||
| 	.user-entry { | ||||
| 		width: 100%; | ||||
| 		padding: 20px; | ||||
| 		margin-bottom: 10px; | ||||
| 	} | ||||
| </style> | ||||
| 
 | ||||
| <script> | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Maxence Lange
						Maxence Lange