Skip to content

Commit 6387314

Browse files
authored
Merge pull request #4285 from bbc/t1535-special-instructions
t1535 - Adds functionality that allows some restrictions text and special instructions text to be defined in config against the rights category and then displayed accordingly in metadata panel
2 parents 5b73aa4 + 3072055 commit 6387314

File tree

24 files changed

+433
-100
lines changed

24 files changed

+433
-100
lines changed

common-lib/src/main/resources/application.conf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,24 @@ usageRightsConfigProvider = {
104104
}
105105
}
106106

107+
# ------------------------------------------------------
108+
# Rights Category Special Instructions and Restrictions
109+
# Variables usageInstructions and usageRestrictions define the rights derived special instructions and restrictions that
110+
# will be displayed along with the metadata for an image but are dervied from the selected rights category
111+
# They are json objects keyed by the rights category key and with the required text as a string variable;
112+
# usageInstructions {
113+
# <<rights category key>> = "<<required text>>"
114+
# }
115+
# usageRestrictions {
116+
# <<rights category key>> = "<<required text>>"
117+
# }
118+
# can be left blank or excluded if not required
119+
# -------------------------------------------------------
120+
usageInstructions {
121+
}
122+
usageRestrictions {
123+
}
124+
107125
# -------------------------------------------------------------
108126
# Announcements - notifications to be seen by users
109127
# Format:

common-lib/src/main/scala/com/gu/mediaservice/model/UsageRights.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ object Agency extends UsageRightsSpec {
219219
val defaultCost = None
220220
def name(commonConfig: CommonConfig) = "Agency - subscription"
221221
def description(commonConfig: CommonConfig) =
222-
"Agencies such as Getty, Reuters, Press Association, etc. where subscription fees are paid to access and use pictures."
222+
"Agencies such as Reuters, Press Association, etc. where subscription fees are paid to access and use pictures."
223223

224224
implicit val formats: Format[Agency] =
225225
UsageRights.subtypeFormat(Agency.category)(Json.format[Agency])
@@ -318,7 +318,7 @@ object OriginalSource extends UsageRightsSpec {
318318
val defaultCost = Some(Free)
319319
def name(commonConfig: CommonConfig) = "Original Source"
320320
def description(commonConfig: CommonConfig) =
321-
"Images provided by members of the public to be shared with Journalist who is out collecting material for stories"
321+
"Images provided by members of the public to be shared with a journalist who is out collecting material for stories."
322322

323323
implicit val formats: Format[OriginalSource] =
324324
UsageRights.subtypeFormat(OriginalSource.category)(Json.format[OriginalSource])
@@ -524,7 +524,7 @@ object Composite extends UsageRightsSpec {
524524
val defaultCost = Some(Free)
525525
def name(commonConfig: CommonConfig) = "Composite"
526526
def description(commonConfig: CommonConfig) =
527-
"Any restricted images within the composite must be identified."
527+
"A composite is an image made from the combination of a variety of stills. Any images within the composite must be listed within the suppliers field."
528528

529529
override val caution = Some("All images should be free to use, or restrictions applied")
530530

@@ -542,7 +542,7 @@ object PublicDomain extends UsageRightsSpec {
542542
def description(commonConfig: CommonConfig) =
543543
"Images out of copyright or bequeathed to the public."
544544

545-
override val caution = Some("ONLY use if out of copyright or bequeathed to public")
545+
override val caution = Some("ONLY use if you are certain the image is out of copyright or bequeathed to public")
546546

547547
implicit val formats: Format[PublicDomain] =
548548
UsageRights.subtypeFormat(PublicDomain.category)(Json.format[PublicDomain])
@@ -554,9 +554,9 @@ final case class ProgramPromotional(restrictions: Option[String] = None) extends
554554
object ProgramPromotional extends UsageRightsSpec {
555555
val category = "program-promotional"
556556
val defaultCost = Some(Pay)
557-
def name(commonConfig: CommonConfig) = "Program Promotional"
557+
def name(commonConfig: CommonConfig) = "Programme Promotional"
558558
def description(commonConfig: CommonConfig) =
559-
"Images supplied for the Promotion of Public broadcast programs"
559+
"Images supplied for the promotion of public broadcast programmes."
560560

561561
implicit val formats: Format[ProgramPromotional] =
562562
UsageRights.subtypeFormat(ProgramPromotional.category)(Json.format[ProgramPromotional])
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
<div ng-switch="messageState">
1+
<div ng-switch="ctrl.messageState">
22
<div ng-switch-when="conditional"
33
class="image-notice image-info__group cost cost--conditional"
44
title="This image can be used but only within certain restrictions">
5-
<b>Restricted use:</b> {{image.data.usageRights.restrictions}}
5+
<b>Restricted use:</b> {{ctrl.restrictionsText()}}
66
</div>
77
</div>
Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,39 @@
11
import angular from 'angular';
2+
import {imageService} from '../../image/service';
3+
import {restrictionsText} from '../../util/rights-categories';
24

35
import template from './gr-image-cost-message.html';
46
import './gr-image-cost-message.css';
57

6-
export const module = angular.module('gr.imageCostMessage', []);
8+
export const module = angular.module('gr.imageCostMessage', [imageService.name]);
79

8-
module.directive('grImageCostMessage', ['imageService', function (imageService) {
10+
module.controller('grImageCostMessage', [
11+
'imageService',
12+
13+
function (imageService) {
14+
let ctrl = this;
15+
16+
ctrl.$onInit = () => {
17+
const states = imageService(ctrl.image).states;
18+
ctrl.messageState = (states.hasRestrictions) ? "conditional" : states.costState;
19+
ctrl.restrictionsText = () => {
20+
return restrictionsText(this.image);
21+
};
22+
23+
};
24+
}
25+
]);
26+
27+
module.directive('grImageCostMessage', [function () {
928
return {
1029
restrict: 'E',
1130
template: template,
1231
transclude: true,
13-
link: scope => {
14-
const { states } = imageService(scope.image);
15-
scope.messageState = states.costState;
16-
},
1732
scope: {
1833
image: '=grImage'
19-
}
34+
},
35+
controller: 'grImageCostMessage',
36+
controllerAs: 'ctrl',
37+
bindToController: true
2038
};
2139
}]);

kahuna/public/js/components/gr-image-metadata/gr-image-metadata.html

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
gr-usage-rights-updated-by-template="ctrl.usageRightsUpdatedByTemplate">
2727
</gr-usage-rights-editor>
2828

29-
<dd class="image-info__title" ng-if="! ctrl.showUsageRights">
30-
<dd ng-if="! ctrl.usageRightsSummary">
29+
<div class="image-info__title" ng-if="!ctrl.showUsageRights">
30+
<dd ng-if="!ctrl.usageRightsSummary">
3131
{{ctrl.usageCategory || 'None'}}
3232
</dd>
3333
<dd ng-if="ctrl.usageRightsSummary">
@@ -36,7 +36,7 @@
3636
props="{'images':ctrl.selectedImages, 'categoryCallback':ctrl.callbackUsageCategory}">
3737
</usage-rights-summary>
3838
</dd>
39-
</dd>
39+
</div>
4040

4141
<button
4242
data-cy="it-edit-usage-rights-button"
@@ -140,7 +140,7 @@
140140
<button data-cy="it-edit-description-button"
141141
class="image-info__edit"
142142
ng-if="ctrl.userCanEdit && ctrl.metadataUpdatedByTemplate.length == 0"
143-
ng-click="descriptionEditForm.$show()"
143+
ng-click="descriptionEditForm.$show(); ctrl.checkDescriptionLength();"
144144
ng-hide="descriptionEditForm.$visible"></button>
145145
<form editable-form name="descriptionEditForm" onaftersave="ctrl.updateDescriptionField('description', $data)">
146146
<div ng-hide="descriptionEditForm.$visible" ng-class="{'image-info--multiple': ctrl.hasMultipleValues(ctrl.rawMetadata.description)}">
@@ -206,55 +206,85 @@
206206
</dl>
207207
</div>
208208

209-
<div class="image-info__group" ng-if="ctrl.rawMetadata.specialInstructions" role="region" aria-label="Special instructions">
209+
<div data-cy="metadata-specialInstructions" role="region" class="image-info__group" aria-label="Special instructions">
210210
<dl class="image-info__wrap">
211211
<dt class="metadata-line metadata-line__key">Special instructions</dt>
212+
<span ng-if="ctrl.metadata.usageInstructions">
213+
<span class="metadata-line__info">{{ctrl.metadata.usageInstructions}}</span>
214+
</span>
212215
<span ng-if="ctrl.metadataUpdatedByTemplate.includes('specialInstructions')">
213216
<div class="metadata-line__info">
214-
<dd class="image-info__special-instructions-preview">{{ctrl.metadata.specialInstructions}}</dd>
217+
<dd class="image-info__description-preview">{{ctrl.metadata.specialInstructions}}</dd>
215218
</div>
216219
</span>
217220
<span ng-if="!ctrl.metadataUpdatedByTemplate.includes('specialInstructions')">
218221
<button class="image-info__edit"
219222
ng-if="ctrl.userCanEdit && ctrl.metadataUpdatedByTemplate.length == 0"
220-
ng-click="specialInstructionsEditForm.$show()"
223+
ng-click="specialInstructionsEditForm.$show(); ctrl.checkSpecialInstructionsLength();"
221224
ng-hide="specialInstructionsEditForm.$visible"></button>
222-
<div class="metadata-line__info" ng-class="{'image-info--multiple': ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)}"
223-
editable-textarea="ctrl.metadata.specialInstructions"
224-
ng-hide="specialInstructionsEditForm.$visible"
225-
onbeforesave="ctrl.updateMetadataField('specialInstructions', $data)"
226-
e:msd-elastic
227-
e:form="specialInstructionsEditForm"
228-
e:ng-class="{'image-info__editor--error': $error,
229-
'image-info__editor--saving': specialInstructionsEditForm.$waiting,
230-
'text-input': true}">
231-
232-
<div ng-if="ctrl.userCanEdit">
233-
<dd ng-if="ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
234-
class="image-info__special-instructions"
235-
>Multiple special instructions (click ✎ to edit <strong>all</strong>)
236-
</dd>
225+
<form editable-form name="specialInstructionsEditForm" onaftersave="ctrl.updateSpecialInstructionsField()">
226+
<div ng-hide="specialInstructionsEditForm.$visible"
227+
ng-class="{'image-info--multiple': ctrl.hasMultipleSpecialInstructions()}">
237228

238-
<dd ng-if="!ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
239-
class="image-info__special-instructions"
240-
>{{ctrl.metadata.specialInstructions}}
241-
</dd>
242-
</div>
229+
<div ng-if="ctrl.userCanEdit">
230+
<dd class="image-info__special-instructions"
231+
ng-if="ctrl.hasMultipleSpecialInstructions()"
232+
>Multiple special instructions (click ✎ to edit <strong>all</strong>)
233+
</dd>
243234

244-
<div ng-if="!ctrl.userCanEdit">
245-
<dd ng-if="ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
246-
class="image-info__special-instructions"
247-
>Multiple special instructions
248-
</dd>
235+
<dd class="image-info__special-instructions"
236+
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
237+
ng-if="!ctrl.hasMultipleSpecialInstructions() && !ctrl.metadata.usageInstructions"
238+
>{{ctrl.metadata.specialInstructions || "Unknown (click ✎ to add)"}}
239+
</dd>
249240

250-
<dd ng-if="!ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
251-
class="image-info__special-instructions"
252-
>{{ctrl.metadata.specialInstructions}}
253-
</dd>
241+
<dd class="image-info__special-instructions"
242+
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
243+
ng-if="!ctrl.hasMultipleSpecialInstructions() && ctrl.metadata.usageInstructions"
244+
>{{ctrl.metadata.specialInstructions || "Click ✎ to add further instructions"}}
245+
</dd>
246+
</div>
247+
248+
<div ng-if="!ctrl.userCanEdit">
249+
<dd class="image-info__special-instructions"
250+
ng-if="ctrl.hasMultipleSpecialInstructions()"
251+
>Multiple special instructions
252+
</dd>
253+
254+
<dd class="image-info__special-instructions"
255+
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
256+
ng-if="!ctrl.hasMultipleSpecialInstructions() && ctrl.metadata.usageInstructions"
257+
>{{ctrl.metadata.specialInstructions || ""}}
258+
</dd>
259+
260+
<dd class="image-info__special-instructions"
261+
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
262+
ng-if="!ctrl.hasMultipleSpecialInstructions() && !ctrl.metadata.usageInstructions"
263+
>{{ctrl.metadata.specialInstructions || "Unknown"}}
264+
</dd>
265+
</div>
266+
</div>
267+
<div
268+
class="metadata-line__info"
269+
editable-textarea="ctrl.metadata.specialInstructions"
270+
ng-hide="specialInstructionsEditForm.$visible"
271+
e:msd-elastic
272+
e:ng-class="{'image-info__editor--error': $error,
273+
'image-info__editor--saving': specialInstructionsEditForm.$waiting,
274+
'text-input': true}"
275+
>
254276
</div>
255-
</div>
277+
<div ng-if="ctrl.userCanEdit && specialInstructionsEditForm.$visible" class="editable-buttons">
278+
<button class="button-cancel" type="button" ng-click="specialInstructionsEditForm.$cancel()">
279+
<gr-icon-label gr-icon="close">Cancel</gr-icon-label>
280+
</button>
281+
<button class="button-save" type="submit">
282+
<gr-icon-label gr-icon="check">Save</gr-icon-label>
283+
</button>
284+
</div>
285+
</form>
256286
</span>
257-
</dl>
287+
</dl>
258288
</div>
259289

260290
<div class="image-info__group" role="region" aria-label="Image metadata">

0 commit comments

Comments
 (0)