diff options
Diffstat (limited to 'client/src/app/videos/+video-watch/video-watch.component.html')
-rw-r--r-- | client/src/app/videos/+video-watch/video-watch.component.html | 290 |
1 files changed, 144 insertions, 146 deletions
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 3df5b7b19..91f77cbf3 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -1,4 +1,4 @@ | |||
1 | <div class="root-row row"> | 1 | <div class="root" [ngClass]="{ 'theater-enabled': theaterEnabled }"> |
2 | <!-- We need the video container for videojs so we just hide it --> | 2 | <!-- We need the video container for videojs so we just hide it --> |
3 | <div id="video-wrapper"> | 3 | <div id="video-wrapper"> |
4 | <div *ngIf="remoteServerDown" class="remote-server-down"> | 4 | <div *ngIf="remoteServerDown" class="remote-server-down"> |
@@ -59,200 +59,198 @@ | |||
59 | 59 | ||
60 | <!-- Video information --> | 60 | <!-- Video information --> |
61 | <div *ngIf="video" class="margin-content video-bottom"> | 61 | <div *ngIf="video" class="margin-content video-bottom"> |
62 | <div class="row fullWidth"> | 62 | <div class="video-info"> |
63 | <div class="col-12 col-lg-auto video-info"> | 63 | <div class="video-info-first-row"> |
64 | <div class="video-info-first-row"> | 64 | <div> |
65 | <div> | 65 | <div class="d-block d-md-none"> <!-- only shown on medium devices, has its conterpart for larger viewports below --> |
66 | <div class="d-block d-sm-none"> <!-- only shown on small devices, has its conterpart for larger viewports below --> | 66 | <h1 class="video-info-name">{{ video.name }}</h1> |
67 | <div i18n class="video-info-date-views"> | ||
68 | Published {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views | ||
69 | </div> | ||
70 | </div> | ||
71 | |||
72 | <div class="d-flex justify-content-between align-items-md-end"> | ||
73 | <div class="d-none d-md-block"> | ||
67 | <h1 class="video-info-name">{{ video.name }}</h1> | 74 | <h1 class="video-info-name">{{ video.name }}</h1> |
75 | |||
68 | <div i18n class="video-info-date-views"> | 76 | <div i18n class="video-info-date-views"> |
69 | Published {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views | 77 | Published {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views |
70 | </div> | 78 | </div> |
71 | </div> | 79 | </div> |
72 | 80 | ||
73 | <div class="d-flex justify-content-between align-items-sm-end"> | 81 | <div class="video-actions-rates"> |
74 | <div class="d-none d-sm-block"> | 82 | <div class="video-actions fullWidth justify-content-end"> |
75 | <h1 class="video-info-name">{{ video.name }}</h1> | 83 | <div |
84 | *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()" | ||
85 | class="action-button action-button-like" role="button" [attr.aria-pressed]="userRating === 'like'" | ||
86 | i18n-title title="Like this video" | ||
87 | > | ||
88 | <my-global-icon iconName="like"></my-global-icon> | ||
89 | </div> | ||
76 | 90 | ||
77 | <div i18n class="video-info-date-views"> | 91 | <div |
78 | Published {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views | 92 | *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()" |
93 | class="action-button action-button-dislike" role="button" [attr.aria-pressed]="userRating === 'dislike'" | ||
94 | i18n-title title="Dislike this video" | ||
95 | > | ||
96 | <my-global-icon iconName="dislike"></my-global-icon> | ||
79 | </div> | 97 | </div> |
80 | </div> | ||
81 | 98 | ||
82 | <div class="video-actions-rates"> | 99 | <div *ngIf="video.support" (click)="showSupportModal()" class="action-button"> |
83 | <div class="video-actions fullWidth justify-content-end"> | 100 | <my-global-icon iconName="heart"></my-global-icon> |
84 | <div | 101 | <span class="icon-text" i18n>Support</span> |
85 | *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()" | 102 | </div> |
86 | class="action-button action-button-like" role="button" [attr.aria-pressed]="userRating === 'like'" | ||
87 | i18n-title title="Like this video" | ||
88 | > | ||
89 | <my-global-icon iconName="like"></my-global-icon> | ||
90 | </div> | ||
91 | 103 | ||
92 | <div | 104 | <div (click)="showShareModal()" class="action-button" role="button"> |
93 | *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()" | 105 | <my-global-icon iconName="share"></my-global-icon> |
94 | class="action-button action-button-dislike" role="button" [attr.aria-pressed]="userRating === 'dislike'" | 106 | <span class="icon-text" i18n>Share</span> |
95 | i18n-title title="Dislike this video" | 107 | </div> |
96 | > | ||
97 | <my-global-icon iconName="dislike"></my-global-icon> | ||
98 | </div> | ||
99 | 108 | ||
100 | <div *ngIf="video.support" (click)="showSupportModal()" class="action-button"> | 109 | <div |
101 | <my-global-icon iconName="heart"></my-global-icon> | 110 | class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside" |
102 | <span class="icon-text" i18n>Support</span> | 111 | *ngIf="isUserLoggedIn()" (openChange)="addContent.openChange($event)" |
112 | > | ||
113 | <div class="action-button action-button-save" ngbDropdownToggle role="button"> | ||
114 | <my-global-icon iconName="playlist-add"></my-global-icon> | ||
115 | <span class="icon-text" i18n>Save</span> | ||
103 | </div> | 116 | </div> |
104 | 117 | ||
105 | <div (click)="showShareModal()" class="action-button" role="button"> | 118 | <div ngbDropdownMenu> |
106 | <my-global-icon iconName="share"></my-global-icon> | 119 | <my-video-add-to-playlist #addContent [video]="video"></my-video-add-to-playlist> |
107 | <span class="icon-text" i18n>Share</span> | ||
108 | </div> | 120 | </div> |
121 | </div> | ||
109 | 122 | ||
110 | <div | 123 | <div class="action-dropdown" ngbDropdown placement="top" role="button"> |
111 | class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside" | 124 | <div class="action-button" ngbDropdownToggle role="button"> |
112 | *ngIf="isUserLoggedIn()" (openChange)="addContent.openChange($event)" | 125 | <my-global-icon class="more-icon" iconName="more-horizontal"></my-global-icon> |
113 | > | ||
114 | <div class="action-button action-button-save" ngbDropdownToggle role="button"> | ||
115 | <my-global-icon iconName="playlist-add"></my-global-icon> | ||
116 | <span class="icon-text" i18n>Save</span> | ||
117 | </div> | ||
118 | |||
119 | <div ngbDropdownMenu> | ||
120 | <my-video-add-to-playlist #addContent [video]="video"></my-video-add-to-playlist> | ||
121 | </div> | ||
122 | </div> | 126 | </div> |
123 | 127 | ||
124 | <div class="action-dropdown" ngbDropdown placement="top" role="button"> | 128 | <div ngbDropdownMenu> |
125 | <div class="action-button" ngbDropdownToggle role="button"> | 129 | <a *ngIf="isVideoDownloadable()" class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)"> |
126 | <my-global-icon class="more-icon" iconName="more-horizontal"></my-global-icon> | 130 | <my-global-icon iconName="download"></my-global-icon> <ng-container i18n>Download</ng-container> |
127 | </div> | 131 | </a> |
128 | 132 | ||
129 | <div ngbDropdownMenu> | 133 | <a *ngIf="isUserLoggedIn()" class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)"> |
130 | <a *ngIf="isVideoDownloadable()" class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)"> | 134 | <my-global-icon iconName="alert"></my-global-icon> <ng-container i18n>Report</ng-container> |
131 | <my-global-icon iconName="download"></my-global-icon> <ng-container i18n>Download</ng-container> | 135 | </a> |
132 | </a> | ||
133 | 136 | ||
134 | <a *ngIf="isUserLoggedIn()" class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)"> | 137 | <a *ngIf="isVideoUpdatable()" class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]"> |
135 | <my-global-icon iconName="alert"></my-global-icon> <ng-container i18n>Report</ng-container> | 138 | <my-global-icon iconName="edit"></my-global-icon> <ng-container i18n>Update</ng-container> |
136 | </a> | 139 | </a> |
137 | 140 | ||
138 | <a *ngIf="isVideoUpdatable()" class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]"> | 141 | <a *ngIf="isVideoBlacklistable()" class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="showBlacklistModal($event)"> |
139 | <my-global-icon iconName="edit"></my-global-icon> <ng-container i18n>Update</ng-container> | 142 | <my-global-icon iconName="no"></my-global-icon> <ng-container i18n>Blacklist</ng-container> |
140 | </a> | 143 | </a> |
141 | 144 | ||
142 | <a *ngIf="isVideoBlacklistable()" class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="showBlacklistModal($event)"> | 145 | <a *ngIf="isVideoUnblacklistable()" class="dropdown-item" i18n-title title="Unblacklist this video" href="#" (click)="unblacklistVideo($event)"> |
143 | <my-global-icon iconName="no"></my-global-icon> <ng-container i18n>Blacklist</ng-container> | 146 | <my-global-icon iconName="undo"></my-global-icon> <ng-container i18n>Unblacklist</ng-container> |
144 | </a> | 147 | </a> |
145 | 148 | ||
146 | <a *ngIf="isVideoUnblacklistable()" class="dropdown-item" i18n-title title="Unblacklist this video" href="#" (click)="unblacklistVideo($event)"> | 149 | <a *ngIf="isVideoRemovable()" class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)"> |
147 | <my-global-icon iconName="undo"></my-global-icon> <ng-container i18n>Unblacklist</ng-container> | 150 | <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete</ng-container> |
148 | </a> | 151 | </a> |
149 | |||
150 | <a *ngIf="isVideoRemovable()" class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)"> | ||
151 | <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete</ng-container> | ||
152 | </a> | ||
153 | </div> | ||
154 | </div> | 152 | </div> |
155 | </div> | 153 | </div> |
154 | </div> | ||
156 | 155 | ||
157 | <div | 156 | <div |
158 | class="video-info-likes-dislikes-bar" | 157 | class="video-info-likes-dislikes-bar" |
159 | *ngIf="video.likes !== 0 || video.dislikes !== 0" | 158 | *ngIf="video.likes !== 0 || video.dislikes !== 0" |
160 | [ngbTooltip]="likesBarTooltipText" | 159 | [ngbTooltip]="likesBarTooltipText" |
161 | placement="bottom" | 160 | placement="bottom" |
162 | > | 161 | > |
163 | <div class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div> | 162 | <div class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div> |
164 | </div> | ||
165 | </div> | 163 | </div> |
166 | </div> | 164 | </div> |
165 | </div> | ||
167 | 166 | ||
168 | 167 | ||
169 | <div class="pt-3 border-top video-info-channel"> | 168 | <div class="pt-3 border-top video-info-channel"> |
170 | <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" i18n-title title="Go the channel page"> | 169 | <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" i18n-title title="Go the channel page"> |
171 | {{ video.channel.displayName }} | 170 | {{ video.channel.displayName }} |
172 | |||
173 | <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" /> | ||
174 | </a> | ||
175 | 171 | ||
176 | <my-subscribe-button #subscribeButton [videoChannel]="video.channel" size="small"></my-subscribe-button> | 172 | <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" /> |
177 | </div> | 173 | </a> |
178 | 174 | ||
179 | <div class="video-info-by"> | 175 | <my-subscribe-button #subscribeButton [videoChannel]="video.channel" size="small"></my-subscribe-button> |
180 | <a [routerLink]="[ '/accounts', video.byAccount ]" i18n-title title="Go to the account page"> | ||
181 | <span i18n>By {{ video.byAccount }}</span> | ||
182 | <img [src]="video.accountAvatarUrl" alt="Account avatar" /> | ||
183 | </a> | ||
184 | </div> | ||
185 | </div> | 176 | </div> |
186 | 177 | ||
178 | <div class="video-info-by"> | ||
179 | <a [routerLink]="[ '/accounts', video.byAccount ]" i18n-title title="Go to the account page"> | ||
180 | <span i18n>By {{ video.byAccount }}</span> | ||
181 | <img [src]="video.accountAvatarUrl" alt="Account avatar" /> | ||
182 | </a> | ||
183 | </div> | ||
187 | </div> | 184 | </div> |
188 | 185 | ||
189 | <div class="video-info-description"> | 186 | </div> |
190 | <div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div> | ||
191 | 187 | ||
192 | <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()"> | 188 | <div class="video-info-description"> |
193 | <ng-container i18n>Show more</ng-container> | 189 | <div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div> |
194 | <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span> | ||
195 | <my-small-loader class="description-loading" [loading]="descriptionLoading"></my-small-loader> | ||
196 | </div> | ||
197 | 190 | ||
198 | <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more"> | 191 | <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()"> |
199 | <ng-container i18n>Show less</ng-container> | 192 | <ng-container i18n>Show more</ng-container> |
200 | <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span> | 193 | <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span> |
201 | </div> | 194 | <my-small-loader class="description-loading" [loading]="descriptionLoading"></my-small-loader> |
202 | </div> | 195 | </div> |
203 | 196 | ||
204 | <div class="video-attributes"> | 197 | <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more"> |
205 | <div class="video-attribute"> | 198 | <ng-container i18n>Show less</ng-container> |
206 | <span i18n class="video-attribute-label">Privacy</span> | 199 | <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span> |
207 | <span class="video-attribute-value">{{ video.privacy.label }}</span> | 200 | </div> |
208 | </div> | 201 | </div> |
209 | 202 | ||
210 | <div *ngIf="!!video.originallyPublishedAt" class="video-attribute"> | 203 | <div class="video-attributes"> |
211 | <span i18n class="video-attribute-label">Originally published</span> | 204 | <div class="video-attribute"> |
212 | <span class="video-attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span> | 205 | <span i18n class="video-attribute-label">Privacy</span> |
213 | </div> | 206 | <span class="video-attribute-value">{{ video.privacy.label }}</span> |
207 | </div> | ||
214 | 208 | ||
215 | <div class="video-attribute"> | 209 | <div *ngIf="!!video.originallyPublishedAt" class="video-attribute"> |
216 | <span i18n class="video-attribute-label">Category</span> | 210 | <span i18n class="video-attribute-label">Originally published</span> |
217 | <span *ngIf="!video.category.id" class="video-attribute-value">{{ video.category.label }}</span> | 211 | <span class="video-attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span> |
218 | <a | 212 | </div> |
219 | *ngIf="video.category.id" class="video-attribute-value" | ||
220 | [routerLink]="[ '/search' ]" [queryParams]="{ categoryOneOf: [ video.category.id ] }" | ||
221 | >{{ video.category.label }}</a> | ||
222 | </div> | ||
223 | 213 | ||
224 | <div class="video-attribute"> | 214 | <div class="video-attribute"> |
225 | <span i18n class="video-attribute-label">Licence</span> | 215 | <span i18n class="video-attribute-label">Category</span> |
226 | <span *ngIf="!video.licence.id" class="video-attribute-value">{{ video.licence.label }}</span> | 216 | <span *ngIf="!video.category.id" class="video-attribute-value">{{ video.category.label }}</span> |
227 | <a | 217 | <a |
228 | *ngIf="video.licence.id" class="video-attribute-value" | 218 | *ngIf="video.category.id" class="video-attribute-value" |
229 | [routerLink]="[ '/search' ]" [queryParams]="{ licenceOneOf: [ video.licence.id ] }" | 219 | [routerLink]="[ '/search' ]" [queryParams]="{ categoryOneOf: [ video.category.id ] }" |
230 | >{{ video.licence.label }}</a> | 220 | >{{ video.category.label }}</a> |
231 | </div> | 221 | </div> |
232 | 222 | ||
233 | <div class="video-attribute"> | 223 | <div class="video-attribute"> |
234 | <span i18n class="video-attribute-label">Language</span> | 224 | <span i18n class="video-attribute-label">Licence</span> |
235 | <span *ngIf="!video.language.id" class="video-attribute-value">{{ video.language.label }}</span> | 225 | <span *ngIf="!video.licence.id" class="video-attribute-value">{{ video.licence.label }}</span> |
236 | <a | 226 | <a |
237 | *ngIf="video.language.id" class="video-attribute-value" | 227 | *ngIf="video.licence.id" class="video-attribute-value" |
238 | [routerLink]="[ '/search' ]" [queryParams]="{ languageOneOf: [ video.language.id ] }" | 228 | [routerLink]="[ '/search' ]" [queryParams]="{ licenceOneOf: [ video.licence.id ] }" |
239 | >{{ video.language.label }}</a> | 229 | >{{ video.licence.label }}</a> |
240 | </div> | 230 | </div> |
241 | 231 | ||
242 | <div class="video-attribute video-attribute-tags"> | 232 | <div class="video-attribute"> |
243 | <span i18n class="video-attribute-label">Tags</span> | 233 | <span i18n class="video-attribute-label">Language</span> |
244 | <a | 234 | <span *ngIf="!video.language.id" class="video-attribute-value">{{ video.language.label }}</span> |
245 | *ngFor="let tag of getVideoTags()" | 235 | <a |
246 | class="video-attribute-value" [routerLink]="[ '/search' ]" [queryParams]="{ tagsOneOf: [ tag ] }" | 236 | *ngIf="video.language.id" class="video-attribute-value" |
247 | >{{ tag }}</a> | 237 | [routerLink]="[ '/search' ]" [queryParams]="{ languageOneOf: [ video.language.id ] }" |
248 | </div> | 238 | >{{ video.language.label }}</a> |
249 | </div> | 239 | </div> |
250 | 240 | ||
251 | <my-video-comments [video]="video" [user]="user"></my-video-comments> | 241 | <div class="video-attribute video-attribute-tags"> |
242 | <span i18n class="video-attribute-label">Tags</span> | ||
243 | <a | ||
244 | *ngFor="let tag of getVideoTags()" | ||
245 | class="video-attribute-value" [routerLink]="[ '/search' ]" [queryParams]="{ tagsOneOf: [ tag ] }" | ||
246 | >{{ tag }}</a> | ||
247 | </div> | ||
252 | </div> | 248 | </div> |
253 | 249 | ||
254 | <my-recommended-videos [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" [user]="user"></my-recommended-videos> | 250 | <my-video-comments [video]="video" [user]="user"></my-video-comments> |
255 | </div> | 251 | </div> |
252 | |||
253 | <my-recommended-videos [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" [user]="user"></my-recommended-videos> | ||
256 | </div> | 254 | </div> |
257 | 255 | ||
258 | <div class="privacy-concerns" *ngIf="hasAlreadyAcceptedPrivacyConcern === false"> | 256 | <div class="privacy-concerns" *ngIf="hasAlreadyAcceptedPrivacyConcern === false"> |