Add Category Pills to Module
This commit is contained in:
parent
475afd03ed
commit
6d312da0ae
|
|
@ -4,12 +4,23 @@
|
||||||
class="module"
|
class="module"
|
||||||
v-if="module.id"
|
v-if="module.id"
|
||||||
>
|
>
|
||||||
<h2
|
<div class="module__header">
|
||||||
class="module__meta-title"
|
<div>
|
||||||
id="meta-title"
|
<h2
|
||||||
>
|
class="module__meta-title"
|
||||||
{{ module.metaTitle }}
|
id="meta-title"
|
||||||
</h2>
|
>
|
||||||
|
{{ module.metaTitle }}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<pill :text="module.category?.name"></pill>
|
||||||
|
<pill :text="module.categoryType?.name"></pill>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<h1
|
<h1
|
||||||
class="module__title"
|
class="module__title"
|
||||||
data-cy="module-title"
|
data-cy="module-title"
|
||||||
|
|
@ -85,116 +96,127 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ObjectiveGroups from '@/components/objective-groups/ObjectiveGroups.vue';
|
import ObjectiveGroups from '@/components/objective-groups/ObjectiveGroups.vue';
|
||||||
import Chapter from '@/components/Chapter.vue';
|
import Chapter from '@/components/Chapter.vue';
|
||||||
import BookmarkActions from '@/components/notes/BookmarkActions.vue';
|
import BookmarkActions from '@/components/notes/BookmarkActions.vue';
|
||||||
|
import Pill from "@/components/ui/Pill.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
module: {
|
module: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
BookmarkActions,
|
Pill,
|
||||||
ObjectiveGroups,
|
BookmarkActions,
|
||||||
Chapter,
|
ObjectiveGroups,
|
||||||
},
|
Chapter,
|
||||||
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
languageCommunicationObjectiveGroups() {
|
languageCommunicationObjectiveGroups() {
|
||||||
return this.module.objectiveGroups
|
return this.module.objectiveGroups
|
||||||
? this.module.objectiveGroups.filter((group) => group.title.toLowerCase() === 'language_communication')
|
? this.module.objectiveGroups.filter((group) => group.title.toLowerCase() === 'language_communication')
|
||||||
: [];
|
: [];
|
||||||
|
},
|
||||||
|
societyObjectiveGroups() {
|
||||||
|
return this.module.objectiveGroups
|
||||||
|
? this.module.objectiveGroups.filter((group) => group.title.toLowerCase() === 'society')
|
||||||
|
: [];
|
||||||
|
},
|
||||||
|
interdisciplinaryObjectiveGroups() {
|
||||||
|
return this.module.objectiveGroups
|
||||||
|
? this.module.objectiveGroups.filter((group) => group.title.toLowerCase() === 'interdisciplinary')
|
||||||
|
: [];
|
||||||
|
},
|
||||||
|
note() {
|
||||||
|
if (!(this.module && this.module.bookmark)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return this.module.bookmark.note;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
societyObjectiveGroups() {
|
};
|
||||||
return this.module.objectiveGroups
|
|
||||||
? this.module.objectiveGroups.filter((group) => group.title.toLowerCase() === 'society')
|
|
||||||
: [];
|
|
||||||
},
|
|
||||||
interdisciplinaryObjectiveGroups() {
|
|
||||||
return this.module.objectiveGroups
|
|
||||||
? this.module.objectiveGroups.filter((group) => group.title.toLowerCase() === 'interdisciplinary')
|
|
||||||
: [];
|
|
||||||
},
|
|
||||||
note() {
|
|
||||||
if (!(this.module && this.module.bookmark)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return this.module.bookmark.note;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import 'styles/helpers';
|
@import 'styles/helpers';
|
||||||
|
|
||||||
.module {
|
.module {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
|
|
||||||
padding: $large-spacing 0;
|
padding: $large-spacing 0;
|
||||||
@include desktop {
|
@include desktop {
|
||||||
width: 800px;
|
width: 800px;
|
||||||
padding: $large-spacing 15px;
|
padding: $large-spacing 15px;
|
||||||
}
|
}
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
&__hero {
|
&__hero {
|
||||||
margin-bottom: 35px;
|
margin-bottom: 35px;
|
||||||
}
|
|
||||||
|
|
||||||
&__hero-image {
|
|
||||||
max-width: 100%;
|
|
||||||
border-radius: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__hero-source {
|
|
||||||
@include tiny-text;
|
|
||||||
line-height: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__meta-title {
|
|
||||||
@include meta-title;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__intro-wrapper {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__intro {
|
|
||||||
> :deep(p) {
|
|
||||||
margin-bottom: $large-spacing;
|
|
||||||
@include lead-paragraph;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> :deep(ul) {
|
&__hero-image {
|
||||||
@include list-parent;
|
max-width: 100%;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
> li {
|
&__hero-source {
|
||||||
@include list-child;
|
@include tiny-text;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta-title {
|
||||||
|
@include meta-title;
|
||||||
|
margin-right: 20px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&__intro-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__intro {
|
||||||
|
> :deep(p) {
|
||||||
|
margin-bottom: $large-spacing;
|
||||||
@include lead-paragraph;
|
@include lead-paragraph;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> :deep(ul) {
|
||||||
|
@include list-parent;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
@include list-child;
|
||||||
|
@include lead-paragraph;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&__bookmark-actions {
|
&__bookmark-actions {
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__objective-groups {
|
&__objective-groups {
|
||||||
margin-bottom: 2 * $large-spacing;
|
margin-bottom: 2 * $large-spacing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@
|
||||||
|
|
||||||
function filterModules() {
|
function filterModules() {
|
||||||
let filteredModules = props.modules;
|
let filteredModules = props.modules;
|
||||||
|
|
||||||
|
|
||||||
if (selectedCategory.value === null) {
|
if (selectedCategory.value === null) {
|
||||||
return props.modules;
|
return props.modules;
|
||||||
}
|
}
|
||||||
|
|
@ -108,14 +110,14 @@
|
||||||
// filter by Lehrjahr
|
// filter by Lehrjahr
|
||||||
if (selectedCategory.value.name !== '---') {
|
if (selectedCategory.value.name !== '---') {
|
||||||
filteredModules = filteredModules.filter((module) => {
|
filteredModules = filteredModules.filter((module) => {
|
||||||
return module.category.id == selectedCategory.value.id;
|
return module.category?.id == selectedCategory.value.id;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//filter by Lernfeld
|
//filter by Lernfeld
|
||||||
if (selectedLernfeld.value.name !== '---') {
|
if (selectedLernfeld.value.name !== '---') {
|
||||||
filteredModules = filteredModules.filter((module) => {
|
filteredModules = filteredModules.filter((module) => {
|
||||||
return module.categoryType.id == selectedLernfeld.value.id;
|
return module.categoryType?.id == selectedLernfeld.value.id;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updateLastModuleCategory(selectedCategory.value);
|
updateLastModuleCategory(selectedCategory.value);
|
||||||
|
|
|
||||||
|
|
@ -17,89 +17,88 @@
|
||||||
<p class="module-teaser__description">
|
<p class="module-teaser__description">
|
||||||
{{ teaser }}
|
{{ teaser }}
|
||||||
</p>
|
</p>
|
||||||
<span :value="attribute" v-for="attribute in [category.name, categoryType.name]">
|
<div class="module-teaser__pills">
|
||||||
<div class="module-teaser__module-category" v-if="attribute">{{attribute}}</div>
|
<pill :text="category?.name"></pill>
|
||||||
</span>
|
<pill :text="categoryType?.name"></pill>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import Pill from "@/components/ui/Pill.vue";
|
||||||
props: ['metaTitle', 'title', 'teaser', 'id', 'slug', 'heroImage', 'category', 'categoryType'],
|
|
||||||
|
|
||||||
computed: {
|
export default {
|
||||||
moduleLink() {
|
components: {Pill},
|
||||||
if (this.slug) {
|
props: ['metaTitle', 'title', 'teaser', 'id', 'slug', 'heroImage', 'category', 'categoryType'],
|
||||||
return {
|
|
||||||
name: 'module',
|
|
||||||
params: {
|
computed: {
|
||||||
slug: this.slug,
|
moduleLink() {
|
||||||
},
|
if (this.slug) {
|
||||||
};
|
return {
|
||||||
} else {
|
name: 'module',
|
||||||
return {};
|
params: {
|
||||||
}
|
slug: this.slug,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import 'styles/helpers';
|
@import 'styles/helpers';
|
||||||
|
|
||||||
.module-teaser {
|
.module-teaser {
|
||||||
box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.12);
|
box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.12);
|
||||||
border: 1px solid #e2e2e2;
|
border: 1px solid #e2e2e2;
|
||||||
height: 390px;
|
height: 390px;
|
||||||
max-width: 380px;
|
max-width: 380px;
|
||||||
width: 100%;
|
|
||||||
border-radius: 12px;
|
|
||||||
overflow: hidden;
|
|
||||||
box-sizing: border-box;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&--small {
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__image {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 150px;
|
border-radius: 12px;
|
||||||
height: 150px;
|
overflow: hidden;
|
||||||
background-position: center;
|
box-sizing: border-box;
|
||||||
background-size: 100% auto;
|
cursor: pointer;
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__body {
|
&--small {
|
||||||
padding: 20px;
|
height: 300px;
|
||||||
}
|
|
||||||
|
|
||||||
&__meta-title {
|
|
||||||
color: $color-silver-dark;
|
|
||||||
margin-bottom: $large-spacing;
|
|
||||||
@include regular-text;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__title {
|
|
||||||
@include heading-3;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__description {
|
|
||||||
line-height: $default-line-height;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__module-category {
|
|
||||||
background-color: rgba(129, 129, 129, 0.99); /* Replace with your desired background color */
|
|
||||||
color: #fff; /* Replace with your desired text color */
|
|
||||||
padding: 10px 20px;
|
|
||||||
border-radius: 40px; /* A high value to make it look like a pill */
|
|
||||||
display: inline-block; /* Ensures the pill takes only the necessary width */
|
|
||||||
margin-right: 10px;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
&__image {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 150px;
|
||||||
|
height: 150px;
|
||||||
|
background-position: center;
|
||||||
|
background-size: 100% auto;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta-title {
|
||||||
|
color: $color-silver-dark;
|
||||||
|
margin-bottom: $large-spacing;
|
||||||
|
@include regular-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
@include heading-3;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__description {
|
||||||
|
line-height: $default-line-height;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pills {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ import Avatar from '@/components/profile/Avatar.vue';
|
||||||
import { defineAsyncComponent } from 'vue';
|
import { defineAsyncComponent } from 'vue';
|
||||||
const TrashIcon = defineAsyncComponent(() => import('@/components/icons/TrashIcon.vue'));
|
const TrashIcon = defineAsyncComponent(() => import('@/components/icons/TrashIcon.vue'));
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Kann das mit me.ts zusammengeführt werden?
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
AvatarUploadForm,
|
AvatarUploadForm,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div class="pill" v-if="props.text">{{ props.text }}</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
text: [];
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import 'styles/helpers';
|
||||||
|
|
||||||
|
.pill {
|
||||||
|
background-color: white; /* Replace with your desired background color */
|
||||||
|
color: #333333; /* Replace with your desired text color */
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 30px;
|
||||||
|
border: 1px solid silver;
|
||||||
|
display: inline-block; /* Ensures the pill takes only the necessary width */
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 2px;
|
||||||
|
@include small-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -14,6 +14,7 @@ export interface Me {
|
||||||
team: any;
|
team: any;
|
||||||
lastTopic: any;
|
lastTopic: any;
|
||||||
readOnly: boolean;
|
readOnly: boolean;
|
||||||
|
lastModuleCategory: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MeQuery {
|
export interface MeQuery {
|
||||||
|
|
@ -30,6 +31,8 @@ export interface Location {
|
||||||
|
|
||||||
type RouteLocation = Location | string;
|
type RouteLocation = Location | string;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: ME_QUERY existiert an einem weiteren Ort. Dieser sollte entfernt werden.
|
||||||
const defaultMe: MeQuery = {
|
const defaultMe: MeQuery = {
|
||||||
me: {
|
me: {
|
||||||
selectedClass: {
|
selectedClass: {
|
||||||
|
|
@ -42,6 +45,7 @@ const defaultMe: MeQuery = {
|
||||||
team: null,
|
team: null,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
lastTopic: undefined,
|
lastTopic: undefined,
|
||||||
|
lastModuleCategory: undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -76,6 +80,10 @@ const getCurrentClassName = (me: Me) => {
|
||||||
return currentClass ? currentClass.name : me.schoolClasses.length ? me.schoolClasses[0].name : '';
|
return currentClass ? currentClass.name : me.schoolClasses.length ? me.schoolClasses[0].name : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getLastModuleCategory = (me: Me) => {
|
||||||
|
return me.lastModuleCategory;
|
||||||
|
}
|
||||||
|
|
||||||
const getMe = () => {
|
const getMe = () => {
|
||||||
const { result } = useQuery(ME_QUERY);
|
const { result } = useQuery(ME_QUERY);
|
||||||
|
|
||||||
|
|
@ -126,6 +134,10 @@ const meMixin = {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return getCurrentClassName(this.$data.me);
|
return getCurrentClassName(this.$data.me);
|
||||||
},
|
},
|
||||||
|
lastModuleCategory(): any {
|
||||||
|
// @ts-ignore
|
||||||
|
return getLastModuleCategory(this.$data.me);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from django.utils import timezone
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
|
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
from books.models import Module, RecentModule
|
from books.models import Module, RecentModule, ModuleCategory
|
||||||
from books.schema.nodes import ModuleNode
|
from books.schema.nodes import ModuleNode
|
||||||
from users.models import SchoolClass, User
|
from users.models import SchoolClass, User
|
||||||
from users.schema import PrivateUserNode
|
from users.schema import PrivateUserNode
|
||||||
|
|
@ -115,6 +115,8 @@ class UpdateLastModuleCategory(relay.ClientIDMutation):
|
||||||
def mutate_and_get_payload(cls, root, info, **args):
|
def mutate_and_get_payload(cls, root, info, **args):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
id = args.get('id')
|
id = args.get('id')
|
||||||
|
module_category = get_object(ModuleCategory, id)
|
||||||
|
|
||||||
User.objects.filter(pk=user.id).update(last_module_category_id=id)
|
|
||||||
|
User.objects.filter(pk=user.id).update(last_module_category_id=module_category.id)
|
||||||
return cls(user=user)
|
return cls(user=user)
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ class ModuleNode(DjangoObjectType):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def resolve_objective_groups(parent, info, **kwargs):
|
def resolve_objective_groups(parent, info, **kwargs):
|
||||||
return parent.objective_groups.all().prefetch_related("hidden_for") @ staticmethod
|
return parent.objective_groups.all().prefetch_related("hidden_for")
|
||||||
|
|
||||||
def resolve_category(self, info, **kwargs):
|
def resolve_category(self, info, **kwargs):
|
||||||
return ModuleCategory.objects.get(pk=self.category_id) if self.category_id else None
|
return ModuleCategory.objects.get(pk=self.category_id) if self.category_id else None
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@ class PrivateUserNode(DjangoObjectType):
|
||||||
"onboarding_visited",
|
"onboarding_visited",
|
||||||
"team",
|
"team",
|
||||||
"read_only",
|
"read_only",
|
||||||
|
"last_module_category"
|
||||||
]
|
]
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
|
|
@ -114,7 +115,6 @@ class PrivateUserNode(DjangoObjectType):
|
||||||
is_teacher = graphene.Boolean()
|
is_teacher = graphene.Boolean()
|
||||||
old_classes = graphene.List(SchoolClassNode)
|
old_classes = graphene.List(SchoolClassNode)
|
||||||
school_classes = graphene.List(SchoolClassNode)
|
school_classes = graphene.List(SchoolClassNode)
|
||||||
last_module_category = graphene.Field(ModuleCategoryNode)
|
|
||||||
|
|
||||||
recent_modules = DjangoFilterConnectionField(
|
recent_modules = DjangoFilterConnectionField(
|
||||||
ModuleNode, filterset_class=RecentModuleFilter
|
ModuleNode, filterset_class=RecentModuleFilter
|
||||||
|
|
@ -163,8 +163,6 @@ class PrivateUserNode(DjangoObjectType):
|
||||||
def resolve_team(self, info, **kwargs):
|
def resolve_team(self, info, **kwargs):
|
||||||
return self.team
|
return self.team
|
||||||
|
|
||||||
def resolve_last_module_category(self, info, **kwargs):
|
|
||||||
return self.last_module_category
|
|
||||||
|
|
||||||
|
|
||||||
class ClassMemberNode(ObjectType):
|
class ClassMemberNode(ObjectType):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue