Merge branch 'hotfix/srf-new-embed-link' into develop

This commit is contained in:
Ramon Wenger 2024-04-09 11:38:05 +02:00
commit c0e93f666d
6 changed files with 89 additions and 62 deletions

View File

@ -26,13 +26,28 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script>
import { graphql } from '@/__generated__'; import gql from 'graphql-tag';
import { LICENSE_ACTIVATION } from '@/router/auth.names'; import { LICENSE_ACTIVATION } from '@/router/auth.names';
import { useQuery } from '@vue/apollo-composable';
import { computed } from 'vue';
const query = graphql(` export default {
data() {
return {
me: {
readOnly: false,
selectedClass: {
readOnly: false,
},
},
licenseActivationLink: {
name: LICENSE_ACTIVATION,
},
};
},
apollo: {
me: {
query: gql`
query ReadOnlyQuery { query ReadOnlyQuery {
me { me {
readOnly readOnly
@ -41,34 +56,30 @@ const query = graphql(`
} }
} }
} }
`); `,
const { result } = useQuery(query, null, {
fetchPolicy: 'cache-only', fetchPolicy: 'cache-only',
}); update({ me }) {
if (!me) {
const me = computed(() => { return {
const me = result.value?.me;
return (
me || {
readOnly: false, readOnly: false,
selectedClass: { selectedClass: {
readOnly: false, readOnly: false,
}, },
};
} }
); return me;
}); },
},
},
const isReadOnly = computed(() => { computed: {
return me.value.readOnly || me.value.selectedClass?.readOnly; readOnlyText() {
}); return this.me.readOnly ? 'Sie besitzen keine aktive Lizenz.' : 'Sie sind in dieser Klasse nicht mehr aktiv.';
},
const readOnlyText = computed(() => { isReadOnly() {
return me.value.readOnly ? 'Sie besitzen keine aktive Lizenz.' : 'Sie sind in dieser Klasse nicht mehr aktiv.'; return this.me.readOnly || this.me.selectedClass?.readOnly;
}); },
},
const licenseActivationLink = {
name: LICENSE_ACTIVATION,
}; };
</script> </script>

View File

@ -61,7 +61,6 @@ const typePolicies = {
keyFields: ['slug'], keyFields: ['slug'],
}, },
PrivateUserNode: { PrivateUserNode: {
keyFields: [], // i should never see anyone else's PrivateUserNode, so this should be a singleton
fields: { fields: {
language: { language: {
read() { read() {

View File

@ -1,7 +1,12 @@
const YOUTUBE = /^(?:https:\/\/)?(?:www.)?(?:youtube.com\/watch\?v=|youtu.be\/)([a-zA-Z0-9_-]{11})(?:.+)?$/; const YOUTUBE = /^(?:https:\/\/)?(?:www.)?(?:youtube.com\/watch\?v=|youtu.be\/)([a-zA-Z0-9_-]{11})(?:.+)?$/;
const VIMEO = /^(?:https:\/\/)?(?:www.)?vimeo.com\/([a-zA-Z0-9]*)$/; const VIMEO = /^(?:https:\/\/)?(?:www.)?vimeo.com\/([a-zA-Z0-9]*)$/;
// const SRF = /^(?:https:\/\/)?(?:www.)?srf.ch\/(?:[\w/-]*)[?&]id=([\w-]+)(?:[&\w=-]*)$/; /*
const SRF = /^(?:https:\/\/)?(?:www.)?srf.ch\/(?:[\w/-]*)[?&]id=([\w-]+)(?:[&\w=-]*)(?:&?startTime=([\d.]+))?/; * Handles URLs like
* - https://www.srf.ch/play/tv/popupvideoplayer?id=6db02b8b-975c-4e3e-8260-f1e6eca1d8ed
* - https://www.srf.ch/play/tv/we-myself--why/video/nein-sagen-so-klappt-es?urn=urn:srf:video:6db02b8b-975c-4e3e-8260-f1e6eca1d8e
*/
const SRF =
/^(?:https:\/\/)?(?:www.)?srf.ch\/(?:[\w/-]*)[?&](?:id=|urn=urn:srf:video:)([\w-]+)(?:[&\w=-]*)(?:&?startTime=([\d.]+))?/;
export function isYoutubeUrl(url: string) { export function isYoutubeUrl(url: string) {
return YOUTUBE.test(url); return YOUTUBE.test(url);

View File

@ -2,14 +2,31 @@ import { getVideoId } from '../../src/helpers/video';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import SrfEmbed from '@/components/videos/SrfEmbed.vue'; import SrfEmbed from '@/components/videos/SrfEmbed.vue';
const url = 'https://www.srf.ch/play/tv/popupvideoplayer?id=6db02b8b-975c-4e3e-8260-f1e6eca1d8ed'; describe('Legacy SRF Video Embed', () => {
const embedUrl = const videoId = '6db02b8b-975c-4e3e-8260-f1e6eca1d8ed';
'https://www.srf.ch/play/embed?urn=urn:srf:video:6db02b8b-975c-4e3e-8260-f1e6eca1d8ed&subdivisions=false'; const url = `https://www.srf.ch/play/tv/popupvideoplayer?id=${videoId}`;
describe('SRF Video Embed', () => { const embedUrl = `https://www.srf.ch/play/embed?urn=urn:srf:video:${videoId}&subdivisions=false`;
it('should return the correct embed url', () => { it('should return the correct embed url', () => {
const videoId = getVideoId(url); const extractedId = getVideoId(url);
const embedId = '6db02b8b-975c-4e3e-8260-f1e6eca1d8ed'; expect(extractedId).toBe(videoId);
expect(videoId).toBe(embedId); });
it('should construct the correct iframe', () => {
const props = {
url,
};
const wrapper = mount(SrfEmbed, {
props,
});
expect(wrapper.attributes('src')).toBe(embedUrl);
});
});
describe('New SRF Video Embed', () => {
const videoId = '6db02b8b-975c-4e3e-8260-f1e6eca1d8ed';
const url = `https://www.srf.ch/play/tv/we-myself--why/video/nein-sagen-so-klappt-es?urn=urn:srf:video:${videoId}`;
const embedUrl = `https://www.srf.ch/play/embed?urn=urn:srf:video:${videoId}&subdivisions=false`;
it('should return the correct embed url', () => {
const extractedId = getVideoId(embedUrl);
expect(extractedId).toBe(videoId);
}); });
it('should construct the correct iframe', () => { it('should construct the correct iframe', () => {
const props = { const props = {

View File

@ -5,7 +5,7 @@ from graphene_django import DjangoObjectType
from api.utils import get_by_id_or_slug from api.utils import get_by_id_or_slug
from portfolio.models import Project, ProjectEntry from portfolio.models import Project, ProjectEntry
from users.models import Role, UserRole from users.models import Role, UserRole, User
from users.schema import PublicUserNode from users.schema import PublicUserNode
@ -13,18 +13,18 @@ class ProjectEntryNode(DjangoObjectType):
class Meta: class Meta:
model = ProjectEntry model = ProjectEntry
interfaces = (relay.Node,) interfaces = (relay.Node,)
fields = ("description", "document_url", "project", "created") fields = ('description', 'document_url', 'project', 'created')
class ProjectNode(DjangoObjectType): class ProjectNode(DjangoObjectType):
pk = graphene.Int() pk = graphene.Int()
entries_count = graphene.Int() entries_count = graphene.Int()
entries = graphene.List(ProjectEntryNode) entries = graphene.List(ProjectEntryNode)
student = graphene.Field(PublicUserNode) owner = graphene.Field(PublicUserNode)
class Meta: class Meta:
model = Project model = Project
filter_fields = ["slug", "appearance"] filter_fields = ['slug', 'appearance']
interfaces = (relay.Node,) interfaces = (relay.Node,)
def resolve_pk(self, *args, **kwargs): def resolve_pk(self, *args, **kwargs):
@ -45,16 +45,11 @@ class PortfolioQuery(object):
def resolve_projects(self, info, **kwargs): def resolve_projects(self, info, **kwargs):
user = info.context.user user = info.context.user
if user.is_superuser: if user.is_superuser:
return Project.objects.all().order_by("-pk") return Project.objects.all().order_by('-pk')
if ( if UserRole.get_role_for_user(user).role == Role.objects.get_default_teacher_role():
UserRole.get_role_for_user(user).role return Project.objects.filter(Q(student__school_classes__in=user.school_classes.all(), final=True) |
== Role.objects.get_default_teacher_role() Q(student=user, final=False)).distinct()
):
return Project.objects.filter(
Q(student__school_classes__in=user.school_classes.all(), final=True)
| Q(student=user, final=False)
).distinct()
return Project.objects.filter(student=user) return Project.objects.filter(student=user)