Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions api/src/Entity/Period.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,23 @@ public function removeScheduleEntry(ScheduleEntry $scheduleEntry): self {
return $this;
}

/**
* All the content nodes used in some activity which is carried out (has a schedule entry) in this period.
*
* @return ContentNode[]
*/
#[ApiProperty(writable: false, example: '["/content_nodes/1a2b3c4d"]')]
#[RelatedCollectionLink(ContentNode::class, ['period' => '$this'])]
#[Groups(['read'])]
public function getContentNodes(): array {
Comment thread
carlobeltrame marked this conversation as resolved.
return array_values(array_unique(array_merge(...array_map(
function (ScheduleEntry $scheduleEntry) {
return $scheduleEntry->activity->getRootContentNode()->getRootDescendants();
},
$this->getScheduleEntries()
)), SORT_REGULAR));
}

/**
* @return MaterialItem[]
*/
Expand Down
13 changes: 12 additions & 1 deletion api/tests/Api/ContentNodes/ContentNode/ReadContentNodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Tests\Api\ContentNodes\ContentNode;

use App\Entity\ContentNode;
use App\Entity\ContentNode\Storyboard;
use App\Tests\Api\ECampApiTestCase;

/**
Expand All @@ -24,7 +25,17 @@ public function testGetSingleContentNodeIsAllowedForCollaborator() {
'contentTypeName' => $contentNode->getContentTypeName(),
'_links' => [
'parent' => ['href' => $this->getIriFor($contentNode->parent)],
'children' => [],
// For performance reasons, children must be an array of hrefs, not a single href to a collection!
// If this test breaks here, that means you probably added a "parent" filter on ContentNode.
// If you really need that filter, see https://github.com/ecamp/ecamp3/pull/2571#discussion_r844089434
// for more info on why it was previously removed. You will then probably have to adapt
// RelatedCollectionLinkNormalizer and add a way to explicitly disable related collection links on a
// specific relation, so that the "parent" filter can co-exist with children being an array.
'children' => [
['href' => $this->getIriFor('multiSelect2')],
['href' => $this->getIriFor('singleText2')],
['href' => $this->getIriFor('storyboard2')],
],
'self' => ['href' => $this->getIriFor('columnLayoutChild1')],
],
]);
Expand Down
40 changes: 40 additions & 0 deletions api/tests/Entity/PeriodTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

namespace App\Tests\Entity;

use App\Entity\Activity;
use App\Entity\Camp;
use App\Entity\ContentNode\ColumnLayout;
use App\Entity\ContentNode\SingleText;
use App\Entity\Day;
use App\Entity\Period;
use App\Entity\ScheduleEntry;
use DateTime;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -33,4 +37,40 @@ public function testFirstDayNumberInPeriod() {
$this->assertEquals(3, $period1->getFirstDayNumber());
$this->assertEquals(1, $period2->getFirstDayNumber());
}

public function testGetContentNodes() {
$camp = new Camp();

$period = new Period();
$period->start = new DateTime('2020-09-14');
$camp->addPeriod($period);
$scheduleEntry1 = new ScheduleEntry();
$scheduleEntry2 = new ScheduleEntry();
$scheduleEntry3 = new ScheduleEntry();
$period->addScheduleEntry($scheduleEntry1);
$period->addScheduleEntry($scheduleEntry2);
$period->addScheduleEntry($scheduleEntry3);

$activity1 = new Activity();
$columnLayout1 = new ColumnLayout();
$singleText1 = new SingleText();
$columnLayout1->addRootDescendant($singleText1);
$columnLayout1->addChild($singleText1);
$activity1->setRootContentNode($columnLayout1);
$scheduleEntry1->activity = $activity1;
$scheduleEntry2->activity = $activity1;

$activity2 = new Activity();
$columnLayout2 = new ColumnLayout();
$singleText2 = new SingleText();
$columnLayout2->addRootDescendant($singleText2);
$columnLayout2->addChild($singleText2);
$activity2->setRootContentNode($columnLayout2);
$scheduleEntry3->activity = $activity2;

$this->assertEquals(
[$singleText1, $columnLayout1, $singleText2, $columnLayout2],
$period->getContentNodes()
);
}
}
49 changes: 0 additions & 49 deletions frontend/src/components/print/PrintConfigurator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,55 +151,6 @@ export default {
lang() {
return this.$store.state.lang.language
},
dataLoading() {
return (
this.camp()._meta.loading ||
this.camp().periods()._meta.loading ||
this.camp()
.periods()
.items.some((period) => {
return (
period._meta.loading ||
period.scheduleEntries()._meta.loading ||
period.scheduleEntries().items.some((scheduleEntry) => {
return (
scheduleEntry._meta.loading ||
scheduleEntry.activity()._meta.loading ||
scheduleEntry.activity().category()._meta.loading ||
scheduleEntry.activity().activityResponsibles()._meta.loading ||
scheduleEntry
.activity()
.activityResponsibles()
.items.some((responsible) => {
return (
responsible._meta.loading ||
responsible.campCollaboration()._meta.loading ||
(responsible.campCollaboration().user() !== null &&
responsible.campCollaboration().user()._meta.loading)
)
}) ||
scheduleEntry.activity().contentNodes()._meta.loading ||
scheduleEntry
.activity()
.contentNodes()
.items.some((contentNode) => {
return (
contentNode._meta.loading ||
contentNode.contentType()._meta.loading
)
})
)
})
)
}) ||
this.camp().materialLists()._meta.loading ||
this.camp()
.materialLists()
.items.some((materialList) => {
return materialList._meta.loading
})
)
},
},
watch: {
lang: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ function ColumnLayout(props) {
const columns = props.contentNode.columns
const firstSlot = columns.length ? columns[0].slot : '1'
const lastSlot = columns.length ? columns[columns.length - 1].slot : '1'
const children = props.allContentNodes.items.filter((contentNode) => {
return (
contentNode.parent &&
contentNode.parent()._meta.self === props.contentNode._meta.self
)
})
const children = props.contentNode.children().items

return (
<View style={{ display: 'flex', flexDirection: 'row' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ const picassoData = (config) => {
.then((activities) => {
return Promise.all(
activities.items.map((activity) => {
return Promise.all([
activity.activityResponsibles().$loadItems(),
activity.contentNodes().$loadItems(),
])
return activity.activityResponsibles().$loadItems()
})
)
}),
Expand All @@ -35,7 +32,10 @@ const picassoData = (config) => {
.then((periods) => {
return Promise.all(
periods.items.map((period) => {
return period.scheduleEntries().$loadItems()
return Promise.all([
period.scheduleEntries().$loadItems(),
period.contentNodes().$loadItems()
])
})
)
}),
Expand All @@ -58,10 +58,7 @@ const activityData = (config) => {
.then((activities) => {
return Promise.all(
activities.items.map((activity) => {
return Promise.all([
activity.activityResponsibles().$loadItems(),
activity.contentNodes().$loadItems(),
])
return activity.activityResponsibles().$loadItems()
})
)
}),
Expand All @@ -79,7 +76,10 @@ const activityData = (config) => {
.then((periods) => {
return Promise.all(
periods.items.map((period) => {
return period.scheduleEntries().$loadItems()
return Promise.all([
period.scheduleEntries().$loadItems(),
period.contentNodes().$loadItems()
])
})
)
}),
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/components/print/print-react/minimalHalJsonVuex.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function isCollection(object) {

function isEntityReference(object) {
if (!object) return false
return isEqualIgnoringOrder(Object.keys(object), ['href'])
return isEqualIgnoringOrder(Object.keys(object), ['href']) || isVirtualLink(object)
}

function isTemplatedLink(object) {
Expand All @@ -21,6 +21,14 @@ function isTemplatedLink(object) {
)
}

function isVirtualLink(object) {
if (!object) return false
return (
isEqualIgnoringOrder(Object.keys(object), ['href', 'virtual']) &&
object.virtual === true
)
}

function normalizeEntityUri(uriOrEntity) {
if (typeof uriOrEntity === 'function') {
uriOrEntity = uriOrEntity()
Expand Down
2 changes: 1 addition & 1 deletion print/components/ProgramPeriod.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default {
await Promise.all([
this.period.days().$loadItems(),
this.period.scheduleEntries().$loadItems(),
this.$api.get().contentNodes({ period: this.period._meta.self }).$loadItems(),
this.period.contentNodes().$loadItems(),
])

this.days = this.period.days().items
Expand Down