Update project entry properties
This commit is contained in:
parent
1f18f0feeb
commit
937c6cff2e
|
|
@ -51,6 +51,6 @@ describe('New project', () => {
|
||||||
cy.get('[data-cy=page-form-input-beschreibung]').should('exist').should('be.empty');
|
cy.get('[data-cy=page-form-input-beschreibung]').should('exist').should('be.empty');
|
||||||
cy.get('[data-cy=page-form-input-ziele]').should('not.exist');
|
cy.get('[data-cy=page-form-input-ziele]').should('not.exist');
|
||||||
cy.get('[data-cy=save-project-button]').click();
|
cy.get('[data-cy=save-project-button]').click();
|
||||||
cy.get('.project-widget:first').contains('random');
|
cy.getByDataCy('project').contains('random');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -46,21 +46,14 @@ describe('Project Entry', () => {
|
||||||
},
|
},
|
||||||
'entriesCount': 1,
|
'entriesCount': 1,
|
||||||
'__typename': 'ProjectNode',
|
'__typename': 'ProjectNode',
|
||||||
'entries': {
|
entries: [
|
||||||
'edges': [{
|
{
|
||||||
'node': {
|
id: 'UHJvamVjdEVudHJ5Tm9kZTo2NQ==',
|
||||||
'id': 'UHJvamVjdEVudHJ5Tm9kZTo2NQ==',
|
description: 'Aktivität:\nKill Thanos\n\n\nReflexion:\nHe sucks\n\n\nNächste Schritte:\nGo for the head',
|
||||||
'activity': 'Kill Thanos',
|
documentUrl: '',
|
||||||
'reflection': 'He sucks',
|
created: '2020-01-20T15:20:31.262510+00:00',
|
||||||
'nextSteps': 'Go for the head',
|
|
||||||
'documentUrl': '',
|
|
||||||
'__typename': 'ProjectEntryNode',
|
|
||||||
'created': '2020-01-20T15:20:31.262510+00:00',
|
|
||||||
},
|
|
||||||
'__typename': 'ProjectEntryNodeEdge',
|
|
||||||
}],
|
|
||||||
'__typename': 'ProjectEntryNodeConnection',
|
|
||||||
},
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AddProjectEntry: variables => ({
|
AddProjectEntry: variables => ({
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,7 @@
|
||||||
const variables = {slug: this.slug};
|
const variables = {slug: this.slug};
|
||||||
const data = store.readQuery({query, variables});
|
const data = store.readQuery({query, variables});
|
||||||
if (data.project && data.project.entries) {
|
if (data.project && data.project.entries) {
|
||||||
data.project.entries.edges.push({
|
data.project.entries.push(projectEntry);
|
||||||
node: projectEntry,
|
|
||||||
__typename: 'ProjectEntryNode'
|
|
||||||
});
|
|
||||||
store.writeQuery({query, variables, data});
|
store.writeQuery({query, variables, data});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,21 +16,11 @@
|
||||||
</li>
|
</li>
|
||||||
</more-options-widget>
|
</more-options-widget>
|
||||||
|
|
||||||
<h3 class="project-entry__heading">Tätigkeit</h3>
|
<h3 class="project-entry__heading">{{ created }}</h3>
|
||||||
<p
|
<p
|
||||||
class="project-entry__paragraph"
|
class="project-entry__paragraph"
|
||||||
data-cy="project-entry-activity">
|
data-cy="project-entry-activity">
|
||||||
{{ activity }}
|
{{ description }}
|
||||||
</p>
|
|
||||||
<h3 class="project-entry__heading">Reflexion</h3>
|
|
||||||
<p class="project-entry__paragraph">
|
|
||||||
{{ reflection }}
|
|
||||||
</p>
|
|
||||||
<h3 class="project-entry__heading">
|
|
||||||
Nächste Schritte
|
|
||||||
</h3>
|
|
||||||
<p class="project-entry__paragraph">
|
|
||||||
{{ nextSteps }}
|
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
class="project-entry__paragraph"
|
class="project-entry__paragraph"
|
||||||
|
|
@ -51,7 +41,7 @@
|
||||||
import PROJECT_QUERY from '@/graphql/gql/queries/projectQuery.gql';
|
import PROJECT_QUERY from '@/graphql/gql/queries/projectQuery.gql';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['activity', 'reflection', 'nextSteps', 'documentUrl', 'created', 'id', 'readOnly'],
|
props: ['description', 'documentUrl', 'created', 'id', 'readOnly'],
|
||||||
components: {
|
components: {
|
||||||
DocumentBlock,
|
DocumentBlock,
|
||||||
MoreOptionsWidget
|
MoreOptionsWidget
|
||||||
|
|
@ -78,7 +68,7 @@
|
||||||
};
|
};
|
||||||
const data = store.readQuery({query, variables});
|
const data = store.readQuery({query, variables});
|
||||||
if (data) {
|
if (data) {
|
||||||
data.project.entries.edges.splice(data.project.entries.edges.findIndex(edge => edge.node.id === projectEntry.id), 1);
|
data.project.entries.splice(data.project.entries.findIndex(entry => entry.id === projectEntry.id), 1);
|
||||||
store.writeQuery({query, variables, data});
|
store.writeQuery({query, variables, data});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -105,6 +95,7 @@
|
||||||
|
|
||||||
&__paragraph {
|
&__paragraph {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__date {
|
&__date {
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@
|
||||||
@import "~styles/helpers";
|
@import "~styles/helpers";
|
||||||
|
|
||||||
.project-entry-modal {
|
.project-entry-modal {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
&__heading {
|
&__heading {
|
||||||
@include heading-3;
|
@include heading-3;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
fragment ProjectEntryParts on ProjectEntryNode {
|
fragment ProjectEntryParts on ProjectEntryNode {
|
||||||
id
|
id
|
||||||
activity
|
description
|
||||||
reflection
|
|
||||||
nextSteps
|
|
||||||
documentUrl
|
documentUrl
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,9 @@ query ProjectQuery($id: ID, $slug: String){
|
||||||
project(slug: $slug, id: $id) {
|
project(slug: $slug, id: $id) {
|
||||||
...ProjectParts
|
...ProjectParts
|
||||||
entries {
|
entries {
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
...ProjectEntryParts
|
...ProjectEntryParts
|
||||||
created
|
created
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import factory
|
||||||
|
|
||||||
from core.factories import fake
|
from core.factories import fake
|
||||||
from portfolio.models import Project, ProjectEntry
|
from portfolio.models import Project, ProjectEntry
|
||||||
|
from users.models import User
|
||||||
|
|
||||||
|
|
||||||
class ProjectFactory(factory.django.DjangoModelFactory):
|
class ProjectFactory(factory.django.DjangoModelFactory):
|
||||||
|
|
@ -14,4 +15,12 @@ class ProjectFactory(factory.django.DjangoModelFactory):
|
||||||
title = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(4, 8)))
|
title = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(4, 8)))
|
||||||
appearance = factory.LazyAttribute(lambda x: random.choice(['red', 'green', 'yellow']))
|
appearance = factory.LazyAttribute(lambda x: random.choice(['red', 'green', 'yellow']))
|
||||||
final = False
|
final = False
|
||||||
|
student = factory.Iterator(User.objects.all())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectEntryFactory(factory.django.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = ProjectEntry
|
||||||
|
|
||||||
|
project = factory.SubFactory(ProjectFactory)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
def migrate_project_entries(ProjectEntry):
|
||||||
|
template = 'Tätigkeit:\n{}\n\n\nReflexion:\n{}\n\n\nNächste Schritte:\n{}'
|
||||||
|
for pe in ProjectEntry.objects.all():
|
||||||
|
pe.description = template.format(pe.activity, pe.reflection, pe.next_steps)
|
||||||
|
pe.save()
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 2.2.22 on 2021-09-28 12:26
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('portfolio', '0006_auto_20210810_1348'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='projectentry',
|
||||||
|
name='description',
|
||||||
|
field=models.TextField(blank=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 2.2.22 on 2021-09-28 12:27
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
from portfolio.migration_helpers import migrate_project_entries
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_project_entries_migration(apps, schema_editor):
|
||||||
|
ProjectEntry = apps.get_model('portfolio', 'ProjectEntry')
|
||||||
|
migrate_project_entries(ProjectEntry)
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('portfolio', '0007_projectentry_description'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(migrate_project_entries_migration)
|
||||||
|
]
|
||||||
|
|
@ -19,8 +19,9 @@ class ProjectEntry(models.Model):
|
||||||
reflection = models.TextField(blank=True)
|
reflection = models.TextField(blank=True)
|
||||||
next_steps = models.TextField(blank=True)
|
next_steps = models.TextField(blank=True)
|
||||||
document_url = models.TextField(blank=True)
|
document_url = models.TextField(blank=True)
|
||||||
|
description = models.TextField(blank=True)
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
project = models.ForeignKey(Project, related_name='entries', on_delete=models.CASCADE)
|
project = models.ForeignKey(Project, related_name='entries', on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.activity
|
return self.description
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,23 @@ import graphene
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectEntryNode(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = ProjectEntry
|
||||||
|
interfaces = (relay.Node,)
|
||||||
|
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)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Project
|
model = Project
|
||||||
|
|
@ -24,11 +31,9 @@ class ProjectNode(DjangoObjectType):
|
||||||
def resolve_entries_count(self, *args, **kwargs):
|
def resolve_entries_count(self, *args, **kwargs):
|
||||||
return self.entries.count()
|
return self.entries.count()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
class ProjectEntryNode(DjangoObjectType):
|
def resolve_entries(root: Project, info, **kwargs):
|
||||||
class Meta:
|
return root.entries.all()
|
||||||
model = ProjectEntry
|
|
||||||
interfaces = (relay.Node,)
|
|
||||||
|
|
||||||
|
|
||||||
class PortfolioQuery(object):
|
class PortfolioQuery(object):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
from api.test_utils import DefaultUserTestCase
|
||||||
|
from core.tests.base_test import SkillboxTestCase
|
||||||
|
from portfolio.factories import ProjectEntryFactory
|
||||||
|
from portfolio.migration_helpers import migrate_project_entries
|
||||||
|
from portfolio.models import ProjectEntry
|
||||||
|
|
||||||
|
ACTIVITY='Kill Thanos'
|
||||||
|
REFLECTION='He sucks'
|
||||||
|
NEXT_STEPS='Go for the head'
|
||||||
|
|
||||||
|
class ProjectEntryMigrationTestCase(SkillboxTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.createDefault()
|
||||||
|
self.project_entry = ProjectEntryFactory(
|
||||||
|
activity=ACTIVITY,
|
||||||
|
reflection=REFLECTION,
|
||||||
|
next_steps=NEXT_STEPS
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_migration(self):
|
||||||
|
self.assertEqual(self.project_entry.description, '')
|
||||||
|
self.assertEqual(self.project_entry.activity, ACTIVITY)
|
||||||
|
self.assertEqual(self.project_entry.reflection, REFLECTION)
|
||||||
|
self.assertEqual(self.project_entry.next_steps, NEXT_STEPS)
|
||||||
|
|
||||||
|
migrate_project_entries(ProjectEntry)
|
||||||
|
|
||||||
|
project_entry = ProjectEntry.objects.get(id=self.project_entry.id)
|
||||||
|
self.assertEqual(project_entry.activity, ACTIVITY)
|
||||||
|
self.assertEqual(project_entry.reflection, REFLECTION)
|
||||||
|
self.assertEqual(project_entry.next_steps, NEXT_STEPS)
|
||||||
|
self.assertEqual(
|
||||||
|
project_entry.description,
|
||||||
|
f'Tätigkeit:\n{ACTIVITY}\n\n\nReflexion:\n{REFLECTION}\n\n\nNächste Schritte:\n{NEXT_STEPS}'
|
||||||
|
)
|
||||||
|
|
@ -857,23 +857,11 @@ type PrivateUserNodeEdge {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectEntryNode implements Node {
|
type ProjectEntryNode implements Node {
|
||||||
id: ID!
|
|
||||||
activity: String!
|
|
||||||
reflection: String!
|
|
||||||
nextSteps: String!
|
|
||||||
documentUrl: String!
|
documentUrl: String!
|
||||||
|
description: String!
|
||||||
created: DateTime!
|
created: DateTime!
|
||||||
project: ProjectNode!
|
project: ProjectNode!
|
||||||
}
|
id: ID!
|
||||||
|
|
||||||
type ProjectEntryNodeConnection {
|
|
||||||
pageInfo: PageInfo!
|
|
||||||
edges: [ProjectEntryNodeEdge]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProjectEntryNodeEdge {
|
|
||||||
node: ProjectEntryNode
|
|
||||||
cursor: String!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectNode implements Node {
|
type ProjectNode implements Node {
|
||||||
|
|
@ -886,7 +874,7 @@ type ProjectNode implements Node {
|
||||||
student: PrivateUserNode!
|
student: PrivateUserNode!
|
||||||
final: Boolean!
|
final: Boolean!
|
||||||
schoolClass: SchoolClassNode
|
schoolClass: SchoolClassNode
|
||||||
entries(offset: Int, before: String, after: String, first: Int, last: Int): ProjectEntryNodeConnection!
|
entries: [ProjectEntryNode]
|
||||||
pk: Int
|
pk: Int
|
||||||
entriesCount: Int
|
entriesCount: Int
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue