Compare commits

...

7 Commits

Author SHA1 Message Date
Tudorel Oprisan
ef4067cbdd fix: replaced pipe with empty string on helper function 2024-10-02 19:16:18 +03:00
Markos Gogoulos
8cc3513a8a docs 2024-10-02 15:57:19 +03:00
Kyle Maas
90e593946d feat: allow commenting by regular users when posting media requires advanced permissions (#1023) 2024-10-02 15:52:30 +03:00
Markos Gogoulos
f7136e2a11 isort 2024-10-02 12:54:47 +03:00
Markos Gogoulos
0151e834a1 black formatting 2024-10-02 12:53:48 +03:00
Markos Gogoulos
5fe4d3a9fc feat: rounded corners 2024-10-02 11:33:17 +03:00
Markos Gogoulos
94c646fdb8 update metadata only, on API call 2024-09-20 19:26:13 +03:00
15 changed files with 240 additions and 139 deletions

View File

@@ -11,6 +11,13 @@ class IsAuthorizedToAdd(permissions.BasePermission):
return user_allowed_to_upload(request)
class IsAuthorizedToAddComment(permissions.BasePermission):
def has_permission(self, request, view):
if request.method in permissions.SAFE_METHODS:
return True
return user_allowed_to_comment(request)
class IsUserOrManager(permissions.BasePermission):
"""To be used in cases where request.user is either the
object owner, or anyone amongst MediaCMS managers
@@ -66,3 +73,24 @@ def user_allowed_to_upload(request):
if request.user.advancedUser:
return True
return False
def user_allowed_to_comment(request):
"""Any custom logic for whether a user is allowed
to comment lives here
"""
if request.user.is_anonymous:
return False
if request.user.is_superuser:
return True
# Default is "all"
if not hasattr(settings, "CAN_COMMENT") or settings.CAN_COMMENT == "all":
return True
elif settings.CAN_COMMENT == "email_verified":
if request.user.email_is_verified:
return True
elif settings.CAN_COMMENT == "advancedUser":
if request.user.advancedUser:
return True
return False

View File

@@ -15,6 +15,10 @@ TIME_ZONE = "Europe/London"
# valid options include 'all', 'email_verified', 'advancedUser'
CAN_ADD_MEDIA = "all"
# who can comment
# valid options include 'all', 'email_verified', 'advancedUser'
CAN_COMMENT = "all"
# valid choices here are 'public', 'private', 'unlisted
PORTAL_WORKFLOW = "public"

View File

@@ -19,6 +19,7 @@
- [16. Frequently Asked Questions](#16-frequently-asked-questions)
- [17. Cookie consent code](#17-cookie-consent-code)
- [18. Disable encoding and show only original file](#18-disable-encoding-and-show-only-original-file)
- [19. Rounded corners on videos](#19-rounded-corners)
## 1. Welcome
This page is created for MediaCMS administrators that are responsible for setting up the software, maintaining it and making modifications.
@@ -478,6 +479,16 @@ Whether or not to enable generation of a sitemap file at http://your_installatio
GENERATE_SITEMAP = False
```
### 5.25 Control who can add comments
By default `CAN_COMMENT = "all"` means that all registered users can add comment. Other valid options are:
- **email_verified**, a user not only has to register an account but also verify the email (by clicking the link sent upon registration). Apparently email configuration need to work, otherise users won't receive emails.
- **advancedUser**, only users that are marked as advanced users can add comment. Admins or MediaCMS managers can make users advanced users by editing their profile and selecting advancedUser.
## 6. Manage pages
to be written
@@ -778,4 +789,15 @@ When videos are uploaded, they are getting encoded to multiple resolutions, a pr
DO_NOT_TRANSCODE_VIDEO = True
```
This will disable the transcoding process and only the original file will be shown. Note that this will also disable the sprites file creation, so you will not have the preview thumbnails on the video player.
This will disable the transcoding process and only the original file will be shown. Note that this will also disable the sprites file creation, so you will not have the preview thumbnails on the video player.
## 19. Rounded corners on videos
By default the video player and media items are now having rounded corners, on larger screens (not in mobile). If you don't like this change, remove the `border-radius` added on the following files:
```
frontend/src/static/css/_extra.css
frontend/src/static/js/components/list-item/Item.scss
frontend/src/static/js/components/media-page/MediaPage.scss
```
you now have to re-run the frontend build in order to see the changes (check docs/dev_exp.md)

View File

@@ -367,7 +367,7 @@ def media_file_info(input_file):
input_file,
]
stdout = run_command(cmd).get("out")
stream_size = sum([int(line) for line in stdout.split("\n") if line != ""])
stream_size = sum([int(line.replace("|", "")) for line in stdout.split("\n") if line != ""])
video_bitrate = round((stream_size * 8 / 1024.0) / video_duration, 2)
if "r_frame_rate" in video_info.keys():

View File

@@ -24,7 +24,12 @@ from rest_framework.views import APIView
from actions.models import USER_MEDIA_ACTIONS, MediaAction
from cms.custom_pagination import FastPaginationWithoutCount
from cms.permissions import IsAuthorizedToAdd, IsUserOrEditor, user_allowed_to_upload
from cms.permissions import (
IsAuthorizedToAdd,
IsAuthorizedToAddComment,
IsUserOrEditor,
user_allowed_to_upload,
)
from users.models import User
from .forms import ContactForm, MediaForm, SubtitleForm
@@ -598,14 +603,15 @@ class MediaDetail(APIView):
media = self.get_object(friendly_token)
if isinstance(media, Response):
return media
serializer = MediaSerializer(media, data=request.data, context={"request": request})
if serializer.is_valid():
if request.data.get('media_file'):
media_file = request.data["media_file"]
serializer.save(user=request.user, media_file=media_file)
else:
serializer.save(user=request.user)
serializer.save(user=request.user)
# no need to update the media file itself, only the metadata
# if request.data.get('media_file'):
# media_file = request.data["media_file"]
# serializer.save(user=request.user, media_file=media_file)
# else:
# serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@@ -1203,7 +1209,7 @@ class CommentDetail(APIView):
Delete comment (DELETE)
"""
permission_classes = (IsAuthorizedToAdd,)
permission_classes = (IsAuthorizedToAddComment,)
parser_classes = (JSONParser, MultiPartParser, FormParser, FileUploadParser)
def get_object(self, friendly_token):

View File

@@ -61,8 +61,8 @@
/* SPACES */
/* ANIMATIONS */
/* FUNCTIONS */
/*@function calc_($expression) {
@return $expression;
/*@function calc_($expression) {
@return $expression;
}*/
/* ANIMATION KEYFRAMES */
@keyframes onHoverFullscreenToggle {
@@ -232,11 +232,11 @@
outline-color: rgba(0, 0, 0, 0);
outline-color: transparent;
/* Doesn't work properly in Safari browser.*/
/*&.vjs-loading-video {
video {
opacity: 0;
visibility: hidden;
}
/*&.vjs-loading-video {
video {
opacity: 0;
visibility: hidden;
}
}*/ }
.video-js.vjs-mediacms video {
width: 100%;
@@ -321,11 +321,11 @@
display: none;
font-size: 0.8125em;
z-index: +1;
/*display:block;
opacity: 0;
height:0;
visibility: hidden;
@include transition( opacity 0.25s cubic-bezier(0.0,0.0,0.2,1) );
/*display:block;
opacity: 0;
height:0;
visibility: hidden;
@include transition( opacity 0.25s cubic-bezier(0.0,0.0,0.2,1) );
will-change:height;*/ }
.video-js.vjs-mediacms .vjs-settings-panel .vjs-setting-panel-title > [role='button'] {
position: relative; }
@@ -337,8 +337,8 @@
outline: 0; }
.video-js.vjs-mediacms .vjs-settings-panel.vjs-visible-panel {
display: block;
/*opacity: 1;
visibility: visible;
/*opacity: 1;
visibility: visible;
height:auto;*/ }
.video-js.vjs-mediacms .vjs-settings-panel .vjs-settings-panel-inner {
display: block;
@@ -679,7 +679,7 @@
.video-js.vjs-mediacms .vjs-volume-panel .vjs-volume-control.vjs-slider-active.vjs-volume-horizontal {
transition: width 0.2s linear;
transition-delay: 0.15s;
/* transition: width 0s linear;
/* transition: width 0s linear;
transition-delay: 0s; */ }
.video-js.vjs-mediacms .vjs-actions-anim {
-webkit-user-select: none;
@@ -986,31 +986,31 @@
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
white-space: normal;
/*@-moz-document url-prefix() {
position: relative;
padding-right: $font-size * 1.1;
overflow: hidden;
&:before {
background-color: $bg-color;
bottom: 0;
position: absolute;
right: 0;
float: right;
text-align:right;
content: '\2026';
width: $font-size * 1.1;
}
&:after {
content: '';
position: absolute;
height: 100%;
width: 100%;
z-index: +1;
background: $bg-color;
}
/*@-moz-document url-prefix() {
position: relative;
padding-right: $font-size * 1.1;
overflow: hidden;
&:before {
background-color: $bg-color;
bottom: 0;
position: absolute;
right: 0;
float: right;
text-align:right;
content: '\2026';
width: $font-size * 1.1;
}
&:after {
content: '';
position: absolute;
height: 100%;
width: 100%;
z-index: +1;
background: $bg-color;
}
}*/
color: #eee; }
.video-js.vjs-mediacms .vjs-corner-layer .title-link:hover {
@@ -1057,28 +1057,28 @@
.video-js.vjs-mediacms:hover .vjs-big-play-button {
background-color: #009933; }
/* @-webkit-keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
}
@keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
/* @-webkit-keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
}
@keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
} */
.video-js.vjs-mediacms .vjs-progress-control .vjs-mouse-display .vjs-time-tooltip,
.video-js.vjs-mediacms .vjs-preview-thumb .vjs-preview-thumb-time-display {

View File

@@ -61,8 +61,8 @@
/* SPACES */
/* ANIMATIONS */
/* FUNCTIONS */
/*@function calc_($expression) {
@return $expression;
/*@function calc_($expression) {
@return $expression;
}*/
/* ANIMATION KEYFRAMES */
@keyframes onHoverFullscreenToggle {
@@ -232,11 +232,11 @@
outline-color: rgba(0, 0, 0, 0);
outline-color: transparent;
/* Doesn't work properly in Safari browser.*/
/*&.vjs-loading-video {
video {
opacity: 0;
visibility: hidden;
}
/*&.vjs-loading-video {
video {
opacity: 0;
visibility: hidden;
}
}*/ }
.video-js.vjs-mediacms video {
width: 100%;
@@ -321,11 +321,11 @@
display: none;
font-size: 0.8125em;
z-index: +1;
/*display:block;
opacity: 0;
height:0;
visibility: hidden;
@include transition( opacity 0.25s cubic-bezier(0.0,0.0,0.2,1) );
/*display:block;
opacity: 0;
height:0;
visibility: hidden;
@include transition( opacity 0.25s cubic-bezier(0.0,0.0,0.2,1) );
will-change:height;*/ }
.video-js.vjs-mediacms .vjs-settings-panel .vjs-setting-panel-title > [role='button'] {
position: relative; }
@@ -337,8 +337,8 @@
outline: 0; }
.video-js.vjs-mediacms .vjs-settings-panel.vjs-visible-panel {
display: block;
/*opacity: 1;
visibility: visible;
/*opacity: 1;
visibility: visible;
height:auto;*/ }
.video-js.vjs-mediacms .vjs-settings-panel .vjs-settings-panel-inner {
display: block;
@@ -679,7 +679,7 @@
.video-js.vjs-mediacms .vjs-volume-panel .vjs-volume-control.vjs-slider-active.vjs-volume-horizontal {
transition: width 0.2s linear;
transition-delay: 0.15s;
/* transition: width 0s linear;
/* transition: width 0s linear;
transition-delay: 0s; */ }
.video-js.vjs-mediacms .vjs-actions-anim {
-webkit-user-select: none;
@@ -986,31 +986,31 @@
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
white-space: normal;
/*@-moz-document url-prefix() {
position: relative;
padding-right: $font-size * 1.1;
overflow: hidden;
&:before {
background-color: $bg-color;
bottom: 0;
position: absolute;
right: 0;
float: right;
text-align:right;
content: '\2026';
width: $font-size * 1.1;
}
&:after {
content: '';
position: absolute;
height: 100%;
width: 100%;
z-index: +1;
background: $bg-color;
}
/*@-moz-document url-prefix() {
position: relative;
padding-right: $font-size * 1.1;
overflow: hidden;
&:before {
background-color: $bg-color;
bottom: 0;
position: absolute;
right: 0;
float: right;
text-align:right;
content: '\2026';
width: $font-size * 1.1;
}
&:after {
content: '';
position: absolute;
height: 100%;
width: 100%;
z-index: +1;
background: $bg-color;
}
}*/
color: #eee; }
.video-js.vjs-mediacms .vjs-corner-layer .title-link:hover {
@@ -1057,28 +1057,28 @@
.video-js.vjs-mediacms:hover .vjs-big-play-button {
background-color: #009933; }
/* @-webkit-keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
}
@keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
/* @-webkit-keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
}
@keyframes vjs-poster-reveal {
0%{
opacity:0;
}
40%{
opacity:0;
}
100%{
opacity:1;
}
} */
.video-js.vjs-mediacms .vjs-progress-control .vjs-mouse-display .vjs-time-tooltip,
.video-js.vjs-mediacms .vjs-preview-thumb .vjs-preview-thumb-time-display {

View File

@@ -0,0 +1,15 @@
body {
/* THIS is not a good way to handle this, and a proper refactoring needs to be performed
This allows bigger images of media on listings for large screens
It would be great to adapt to other sizes, but this requires a good refaftoring
*/
@media screen and (min-width: 2200px) {
--default-item-width: 342px !important;
--default-max-item-width: 342px !important;
--default-item-margin-right-width: 17px !important;
--default-item-margin-bottom-width: 27px !important;
}
}

View File

@@ -13,6 +13,11 @@
.item-thumb,
a.item-thumb {
@media screen and (min-width: 480px) {
border-radius: 10px;
}
position: relative;
display: block;
height: auto;

View File

@@ -530,7 +530,14 @@
}
}
.viewer-container .player-container {
@media screen and (min-width: 480px) {
border-radius: 10px;
}
}
.viewer-container .player-container.audio-player-container {
@media screen and (min-width: 480px) {
padding-top: 0.75 * 56.25%;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
body {
/* THIS is not a good way to handle this, and a proper refactoring needs to be performed
This allows bigger images of media on listings for large screens
It would be great to adapt to other sizes, but this requires a good refaftoring
*/
@media screen and (min-width: 2200px) {
--default-item-width: 342px !important;
--default-max-item-width: 342px !important;
--default-item-margin-right-width: 17px !important;
--default-item-margin-bottom-width: 27px !important;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
import os
import re
import shutil
import os
import uuid
from io import StringIO
from os.path import join
@@ -34,7 +34,6 @@ class BaseFineUploader(object):
self.storage_class = settings.FILE_STORAGE
self.real_path = None
@property
def finished(self):
return self.real_path is not None