Skip to content

Commit 6732d61

Browse files
authored
Merge pull request #1346 from UN-OCHA/berliner/HPC-9947
HPC-9947: Add new plan element for plan caseload trend charts
2 parents 14e03d1 + 3c60631 commit 6732d61

File tree

51 files changed

+2507
-1003
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2507
-1003
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,15 @@ place them in **_.docksal_/backups**
127127
To import a snapshot and run all the steps that a deployment would run please
128128
use this command:
129129

130-
fin post-deploy -i
130+
fin deploy -i
131131

132132
If you have multiple database snapshots available locally, running this command
133133
will let you select which one you want to import.
134134
Running this without the _-i_ argument, will just run the deployment actions on
135135
the current database without importing a snapshot.
136136

137137

138-
Data migrations
138+
DATA MIGRATIONS
139139
---------------
140140

141141
The data migrations can be run locally with this command:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Drupal\ghi_base_objects\Entity;
4+
5+
use Drupal\ghi_base_objects\ApiObjects\Country;
6+
7+
/**
8+
* Provides an interface for defining base object that have a focus country.
9+
*
10+
* @ingroup ghi_base_objects
11+
*/
12+
interface BaseObjectFocusCountryInterface {
13+
14+
/**
15+
* Get the focus country for the plan.
16+
*
17+
* @return \Drupal\ghi_base_objects\Entity\BaseObjectInterface|null
18+
* The country base object or NULL.
19+
*/
20+
public function getFocusCountry();
21+
22+
/**
23+
* Get the focus country override for the plan.
24+
*
25+
* @return object|null
26+
* A latLng object or NULL.
27+
*/
28+
public function getFocusCountryOverride();
29+
30+
/**
31+
* Get the focus country map location for the plan.
32+
*
33+
* @return \Drupal\ghi_base_objects\ApiObjects\Country|null
34+
* An object describing the map location or NULL.
35+
*/
36+
public function getFocusCountryMapLocation(?Country $default_country = NULL);
37+
38+
}

html/modules/custom/ghi_base_objects/src/Entity/BaseObjectInterface.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use Drupal\Core\Entity\EntityChangedInterface;
77

88
/**
9-
* Provides an interface for defining Base object entities.
9+
* Provides an interface for defining base object entities.
1010
*
1111
* @ingroup ghi_base_objects
1212
*/

html/modules/custom/ghi_base_objects/src/Entity/BaseObjectMetaDataInterface.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Drupal\ghi_base_objects\Entity;
44

55
/**
6-
* Provides an interface for defining Base object entities.
6+
* Provides an interface for defining base object entities with meta data.
77
*
88
* @ingroup ghi_base_objects
99
*/

html/modules/custom/ghi_base_objects/tests/src/Functional/BaseObjectFormTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ protected function setUp(): void {
5858
public function testBaseObjectEditForm() {
5959
$base_object = $this->createBaseObject([
6060
'type' => 'plan',
61+
'field_year' => 2025,
6162
]);
6263
$this->drupalGet($base_object->toUrl('edit-form')->toString());
6364
$assert_session = $this->assertSession();

html/modules/custom/ghi_base_objects/tests/src/Kernel/BaseObjectTest.php

+30-19
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use Drupal\Core\Url;
66
use Drupal\KernelTests\KernelTestBase;
77
use Drupal\Tests\ghi_base_objects\Traits\BaseObjectTestTrait;
8-
use Drupal\ghi_base_objects\Entity\BaseObjectType;
98

109
/**
1110
* Tests the base object entity.
@@ -112,15 +111,11 @@ public function testBaseObjectSourceId() {
112111
$this->assertEquals(20, $base_object->getSourceId());
113112
$this->assertEquals('plan--20', $base_object->getUniqueIdentifier());
114113

115-
$base_object_type_incomplete = BaseObjectType::create([
116-
'id' => $this->randomMachineName(),
117-
'label' => $this->randomString(),
118-
'hasYear' => FALSE,
119-
]);
114+
$base_object_type_incomplete = $this->createBaseObjectType();
120115
$base_object = $this->createBaseObject([
121116
'type' => $base_object_type_incomplete->id(),
122117
'name' => 'base_object_name',
123-
'field_original_id' => 20,
118+
'field_original_id' => NULL,
124119
]);
125120
$this->assertNull($base_object->getSourceId());
126121
}
@@ -129,20 +124,12 @@ public function testBaseObjectSourceId() {
129124
* Tests base object needsYear() method.
130125
*/
131126
public function testBaseObjectNeedsYear() {
132-
$base_object_type = $this->createBaseObjectType([
133-
'hasYear' => FALSE,
134-
]);
135-
$base_object = $this->createBaseObject([
136-
'type' => $base_object_type->id(),
137-
]);
127+
$base_object_type = $this->createBaseObjectType();
128+
$base_object = $this->createBaseObject(['type' => $base_object_type->id()]);
138129
$this->assertTrue($base_object->needsYear());
139130

140-
$base_object_type = $this->createBaseObjectType([
141-
'hasYear' => TRUE,
142-
]);
143-
$base_object = $this->createBaseObject([
144-
'type' => $base_object_type->id(),
145-
]);
131+
$base_object_type = $this->createBaseObjectType(['field_year' => 'Year']);
132+
$base_object = $this->createBaseObject(['type' => $base_object_type->id()]);
146133
$this->assertFalse($base_object->needsYear());
147134
}
148135

@@ -158,4 +145,28 @@ public function testBaseObjectCreatedTime() {
158145
$this->assertEquals($timestamp, $base_object->getCreatedTime());
159146
}
160147

148+
/**
149+
* Tests base object created timestamps.
150+
*/
151+
public function testApiCacheTagsToInvalidate() {
152+
$this->createBaseObjectType(['id' => 'custom_base_object_type']);
153+
$base_object = $this->createBaseObject([
154+
'type' => 'custom_base_object_type',
155+
'field_original_id' => 20,
156+
]);
157+
$cache_tags = $base_object->getApiCacheTagsToInvalidate();
158+
$this->assertNotEmpty($cache_tags);
159+
$this->assertIsArray($cache_tags);
160+
$this->assertArrayHasKey(0, $cache_tags);
161+
$this->assertEquals('custom_base_object_type_id:20', $cache_tags[0]);
162+
163+
$base_object = $this->createBaseObject([
164+
'type' => 'custom_base_object_type',
165+
'field_original_id' => NULL,
166+
]);
167+
$cache_tags = $base_object->getApiCacheTagsToInvalidate();
168+
$this->assertEmpty($cache_tags);
169+
$this->assertIsArray($cache_tags);
170+
}
171+
161172
}

html/modules/custom/ghi_base_objects/tests/src/Traits/BaseObjectTestTrait.php

+25-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Drupal\ghi_base_objects\Entity\BaseObjectInterface;
77
use Drupal\ghi_base_objects\Entity\BaseObjectType;
88
use Drupal\ghi_base_objects\Entity\BaseObjectTypeInterface;
9+
use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
910

1011
/**
1112
* Provides methods to create base objects in tests.
@@ -15,17 +16,21 @@
1516
trait BaseObjectTestTrait {
1617

1718
use FieldTestTrait;
19+
use EntityReferenceFieldCreationTrait;
1820

1921
/**
2022
* Create a base object type.
2123
*
2224
* @param mixed[] $values
23-
* (optional) Additional values for the base object type entity:
25+
* (optional) Additional key-value pairs for the base object type entity:
2426
* - id: The ID of the base object type. If none is provided, a random value
2527
* will be used.
2628
* - label: The human-readable label of the base object type. If none is
2729
* provided, a random value will be used.
28-
* - hasYear: Whether the base object type handles years already.
30+
* - field_year: When not empty, this will create a year field with the
31+
* provided label.
32+
* - field_plan: When not empty, this will create a plan field with the
33+
* provided label.
2934
*
3035
* @return \Drupal\ghi_base_objects\Entity\BaseObjectTypeInterface
3136
* A base object type.
@@ -37,14 +42,25 @@ protected function createBaseObjectType(array $values = []) {
3742
$values += [
3843
'id' => $this->randomMachineName(),
3944
'label' => $this->randomString(),
40-
'hasYear' => FALSE,
45+
'hasYear' => !empty($values['field_year']),
46+
'field_year' => NULL,
47+
'field_plan' => NULL,
4148
];
42-
$base_object_type = BaseObjectType::create($values);
43-
$this->assertSame(SAVED_NEW, $base_object_type->save());
44-
$this->assertInstanceOf(BaseObjectTypeInterface::class, $base_object_type);
45-
$this->createField('base_object', $base_object_type->id(), 'integer', 'field_original_id', 'Source id');
46-
if (!empty($values['hasYear'])) {
47-
$this->createField('base_object', $base_object_type->id(), 'integer', 'field_year', 'Year');
49+
$base_object_type = BaseObjectType::load($values['id']) ?: BaseObjectType::create($values);
50+
if ($base_object_type->isNew()) {
51+
$this->assertSame(SAVED_NEW, $base_object_type->save());
52+
$this->assertInstanceOf(BaseObjectTypeInterface::class, $base_object_type);
53+
$this->createField('base_object', $base_object_type->id(), 'integer', 'field_original_id', 'Source id');
54+
if (!empty($values['field_year'])) {
55+
$this->createField('base_object', $base_object_type->id(), 'integer', 'field_year', $values['field_year']);
56+
}
57+
if (!empty($values['field_plan'])) {
58+
$this->createEntityReferenceField('base_object', $base_object_type->id(), 'field_plan', $values['field_plan'], 'base_object', 'default', [
59+
'target_bundles' => [
60+
'plan' => 'plan',
61+
],
62+
]);
63+
}
4864
}
4965
return $base_object_type;
5066
}

html/modules/custom/ghi_blocks/src/Plugin/Block/GHIBlockBase.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ public function hasDefaultTitle() {
284284
/**
285285
* Get the default title.
286286
*
287-
* @return string
287+
* @return \Drupal\Core\StringTranslation\TranslatableMarkup|string
288288
* The default title if one is set in the plugin definition.
289289
*/
290290
public function getDefaultTitle() {

html/modules/custom/ghi_blocks/src/Plugin/Block/GlobalPage/PlanTable.php

+21-65
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Drupal\ghi_blocks\Traits\GlobalSettingsTrait;
1313
use Drupal\ghi_blocks\Traits\PlanFootnoteTrait;
1414
use Drupal\ghi_blocks\Traits\TableSoftLimitTrait;
15+
use Drupal\ghi_blocks\Traits\TableTrait;
1516
use Drupal\ghi_plans\ApiObjects\Mocks\PlanOverviewPlanMock;
1617
use Drupal\ghi_plans\Traits\FtsLinkTrait;
1718
use Drupal\hpc_common\Helpers\ArrayHelper;
@@ -44,6 +45,7 @@ class PlanTable extends GHIBlockBase implements HPCDownloadExcelInterface, HPCDo
4445
use GlobalPlanOverviewBlockTrait;
4546
use GlobalSettingsTrait;
4647
use PlanFootnoteTrait;
48+
use TableTrait;
4749
use TableSoftLimitTrait;
4850
use BlockCommentTrait;
4951
use FtsLinkTrait;
@@ -142,62 +144,22 @@ public function buildTableData($export = FALSE) {
142144
$header += [
143145
'name' => $this->t('Plans'),
144146
'type' => $this->t('Plan type'),
145-
'inneed' => [
146-
'data' => $this->t('People in need'),
147-
'data-column-type' => 'amount',
148-
],
149-
'targeted' => [
150-
'data' => $this->t('People targeted'),
151-
'data-column-type' => 'amount',
152-
],
153-
'expected_reach' => [
154-
'data' => $this->t('Estimated Reach'),
155-
'data-column-type' => 'amount',
156-
],
157-
'expected_reached' => [
158-
'data' => $this->t('% Reached'),
159-
'data-column-type' => 'amount',
160-
],
161-
'latest_reach' => [
162-
'data' => $this->t('People reached'),
163-
'data-column-type' => 'percentage',
164-
],
165-
'reached' => [
166-
'data' => $this->t('% Reached'),
167-
'data-column-type' => 'percentage',
168-
],
169-
'requirements' => [
170-
'data' => $this->t('Requirements'),
171-
'data-column-type' => 'currency',
172-
],
173-
'funding' => [
174-
'data' => $this->t('Funding'),
175-
'data-column-type' => 'currency',
176-
],
177-
'coverage' => [
178-
'data' => $this->t('% Funded'),
179-
'data-column-type' => 'percentage',
180-
],
181-
'status' => [
182-
'data' => $this->t('Status'),
183-
'data-column-type' => 'status',
184-
'sortable' => FALSE,
185-
],
147+
'inneed' => $this->buildHeaderColumn($this->t('People in need'), 'amount'),
148+
'targeted' => $this->buildHeaderColumn($this->t('People targeted'), 'amount'),
149+
'expected_reach' => $this->buildHeaderColumn($this->t('Estimated Reach'), 'amount'),
150+
'expected_reached' => $this->buildHeaderColumn($this->t('% Reached'), 'percentage'),
151+
'latest_reach' => $this->buildHeaderColumn($this->t('People reached'), 'percentage'),
152+
'reached' => $this->buildHeaderColumn($this->t('% Reached'), 'percentage'),
153+
'requirements' => $this->buildHeaderColumn($this->t('Requirements'), 'currency'),
154+
'funding' => $this->buildHeaderColumn($this->t('Funding'), 'currency'),
155+
'coverage' => $this->buildHeaderColumn($this->t('% Funded'), 'percentage'),
156+
'status' => $this->buildHeaderColumn($this->t('Status'), 'status'),
186157
];
187158
if ($export) {
188159
$header['in_gho'] = $this->t('In GHO');
189-
$header['document'] = [
190-
'data' => $this->t('Document'),
191-
'data-column-type' => 'document',
192-
];
193-
$header['link_ha'] = [
194-
'data' => $this->t('Link to HA page'),
195-
'data-column-type' => 'document',
196-
];
197-
$header['link_fts'] = [
198-
'data' => $this->t('Link to FTS page'),
199-
'data-column-type' => 'document',
200-
];
160+
$header['document'] = $this->buildHeaderColumn($this->t('Document'), 'document');
161+
$header['link_ha'] = $this->buildHeaderColumn($this->t('Link to HA page'), 'document');
162+
$header['link_fts'] = $this->buildHeaderColumn($this->t('Link to FTS page'), 'document');
201163
}
202164

203165
$cache_tags = [];
@@ -241,19 +203,15 @@ public function buildTableData($export = FALSE) {
241203
$document_uri = $plan->getPlanDocumentUri();
242204

243205
// Setup the column values.
244-
$value_in_need = $in_need ? [
206+
$value_in_need = [
245207
'#theme' => 'hpc_amount',
246-
'#amount' => $in_need,
208+
'#amount' => $in_need ?: '-',
247209
'#decimals' => $decimals,
248-
] : [
249-
'#markup' => '-',
250210
];
251-
$value_targeted = $target ? [
211+
$value_targeted = [
252212
'#theme' => 'hpc_amount',
253-
'#amount' => $target,
213+
'#amount' => $target ?: '-',
254214
'#decimals' => $decimals,
255-
] : [
256-
'#markup' => '-',
257215
];
258216
$value_expected_reach = [
259217
'#theme' => 'hpc_amount',
@@ -264,12 +222,10 @@ public function buildTableData($export = FALSE) {
264222
'#theme' => 'hpc_percent',
265223
'#ratio' => $expected_reached / 100,
266224
];
267-
$value_latest_reached = $latest_reached !== NULL ? [
225+
$value_latest_reached = [
268226
'#theme' => 'hpc_amount',
269-
'#amount' => $latest_reached,
227+
'#amount' => $latest_reached ?? $this->t('Pending'),
270228
'#decimals' => $decimals,
271-
] : [
272-
'#markup' => $this->t('Pending'),
273229
];
274230
$value_reached = $reached_percent ? [
275231
'#theme' => 'hpc_percent',

0 commit comments

Comments
 (0)