Skip to content

Commit

Permalink
Merge pull request guardian#4285 from bbc/t1535-special-instructions
Browse files Browse the repository at this point in the history
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
  • Loading branch information
paperboyo authored Jul 8, 2024
2 parents 5b73aa4 + 3072055 commit 6387314
Show file tree
Hide file tree
Showing 24 changed files with 433 additions and 100 deletions.
18 changes: 18 additions & 0 deletions common-lib/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ usageRightsConfigProvider = {
}
}

# ------------------------------------------------------
# Rights Category Special Instructions and Restrictions
# Variables usageInstructions and usageRestrictions define the rights derived special instructions and restrictions that
# will be displayed along with the metadata for an image but are dervied from the selected rights category
# They are json objects keyed by the rights category key and with the required text as a string variable;
# usageInstructions {
# <<rights category key>> = "<<required text>>"
# }
# usageRestrictions {
# <<rights category key>> = "<<required text>>"
# }
# can be left blank or excluded if not required
# -------------------------------------------------------
usageInstructions {
}
usageRestrictions {
}

# -------------------------------------------------------------
# Announcements - notifications to be seen by users
# Format:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ object Agency extends UsageRightsSpec {
val defaultCost = None
def name(commonConfig: CommonConfig) = "Agency - subscription"
def description(commonConfig: CommonConfig) =
"Agencies such as Getty, Reuters, Press Association, etc. where subscription fees are paid to access and use pictures."
"Agencies such as Reuters, Press Association, etc. where subscription fees are paid to access and use pictures."

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

implicit val formats: Format[OriginalSource] =
UsageRights.subtypeFormat(OriginalSource.category)(Json.format[OriginalSource])
Expand Down Expand Up @@ -524,7 +524,7 @@ object Composite extends UsageRightsSpec {
val defaultCost = Some(Free)
def name(commonConfig: CommonConfig) = "Composite"
def description(commonConfig: CommonConfig) =
"Any restricted images within the composite must be identified."
"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."

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

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

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

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

implicit val formats: Format[ProgramPromotional] =
UsageRights.subtypeFormat(ProgramPromotional.category)(Json.format[ProgramPromotional])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div ng-switch="messageState">
<div ng-switch="ctrl.messageState">
<div ng-switch-when="conditional"
class="image-notice image-info__group cost cost--conditional"
title="This image can be used but only within certain restrictions">
<b>Restricted use:</b> {{image.data.usageRights.restrictions}}
<b>Restricted use:</b> {{ctrl.restrictionsText()}}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
import angular from 'angular';
import {imageService} from '../../image/service';
import {restrictionsText} from '../../util/rights-categories';

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

export const module = angular.module('gr.imageCostMessage', []);
export const module = angular.module('gr.imageCostMessage', [imageService.name]);

module.directive('grImageCostMessage', ['imageService', function (imageService) {
module.controller('grImageCostMessage', [
'imageService',

function (imageService) {
let ctrl = this;

ctrl.$onInit = () => {
const states = imageService(ctrl.image).states;
ctrl.messageState = (states.hasRestrictions) ? "conditional" : states.costState;
ctrl.restrictionsText = () => {
return restrictionsText(this.image);
};

};
}
]);

module.directive('grImageCostMessage', [function () {
return {
restrict: 'E',
template: template,
transclude: true,
link: scope => {
const { states } = imageService(scope.image);
scope.messageState = states.costState;
},
scope: {
image: '=grImage'
}
},
controller: 'grImageCostMessage',
controllerAs: 'ctrl',
bindToController: true
};
}]);
106 changes: 68 additions & 38 deletions kahuna/public/js/components/gr-image-metadata/gr-image-metadata.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
gr-usage-rights-updated-by-template="ctrl.usageRightsUpdatedByTemplate">
</gr-usage-rights-editor>

<dd class="image-info__title" ng-if="! ctrl.showUsageRights">
<dd ng-if="! ctrl.usageRightsSummary">
<div class="image-info__title" ng-if="!ctrl.showUsageRights">
<dd ng-if="!ctrl.usageRightsSummary">
{{ctrl.usageCategory || 'None'}}
</dd>
<dd ng-if="ctrl.usageRightsSummary">
Expand All @@ -36,7 +36,7 @@
props="{'images':ctrl.selectedImages, 'categoryCallback':ctrl.callbackUsageCategory}">
</usage-rights-summary>
</dd>
</dd>
</div>

<button
data-cy="it-edit-usage-rights-button"
Expand Down Expand Up @@ -140,7 +140,7 @@
<button data-cy="it-edit-description-button"
class="image-info__edit"
ng-if="ctrl.userCanEdit && ctrl.metadataUpdatedByTemplate.length == 0"
ng-click="descriptionEditForm.$show()"
ng-click="descriptionEditForm.$show(); ctrl.checkDescriptionLength();"
ng-hide="descriptionEditForm.$visible"></button>
<form editable-form name="descriptionEditForm" onaftersave="ctrl.updateDescriptionField('description', $data)">
<div ng-hide="descriptionEditForm.$visible" ng-class="{'image-info--multiple': ctrl.hasMultipleValues(ctrl.rawMetadata.description)}">
Expand Down Expand Up @@ -206,55 +206,85 @@
</dl>
</div>

<div class="image-info__group" ng-if="ctrl.rawMetadata.specialInstructions" role="region" aria-label="Special instructions">
<div data-cy="metadata-specialInstructions" role="region" class="image-info__group" aria-label="Special instructions">
<dl class="image-info__wrap">
<dt class="metadata-line metadata-line__key">Special instructions</dt>
<span ng-if="ctrl.metadata.usageInstructions">
<span class="metadata-line__info">{{ctrl.metadata.usageInstructions}}</span>
</span>
<span ng-if="ctrl.metadataUpdatedByTemplate.includes('specialInstructions')">
<div class="metadata-line__info">
<dd class="image-info__special-instructions-preview">{{ctrl.metadata.specialInstructions}}</dd>
<dd class="image-info__description-preview">{{ctrl.metadata.specialInstructions}}</dd>
</div>
</span>
<span ng-if="!ctrl.metadataUpdatedByTemplate.includes('specialInstructions')">
<button class="image-info__edit"
ng-if="ctrl.userCanEdit && ctrl.metadataUpdatedByTemplate.length == 0"
ng-click="specialInstructionsEditForm.$show()"
ng-click="specialInstructionsEditForm.$show(); ctrl.checkSpecialInstructionsLength();"
ng-hide="specialInstructionsEditForm.$visible"></button>
<div class="metadata-line__info" ng-class="{'image-info--multiple': ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)}"
editable-textarea="ctrl.metadata.specialInstructions"
ng-hide="specialInstructionsEditForm.$visible"
onbeforesave="ctrl.updateMetadataField('specialInstructions', $data)"
e:msd-elastic
e:form="specialInstructionsEditForm"
e:ng-class="{'image-info__editor--error': $error,
'image-info__editor--saving': specialInstructionsEditForm.$waiting,
'text-input': true}">

<div ng-if="ctrl.userCanEdit">
<dd ng-if="ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
class="image-info__special-instructions"
>Multiple special instructions (click ✎ to edit <strong>all</strong>)
</dd>
<form editable-form name="specialInstructionsEditForm" onaftersave="ctrl.updateSpecialInstructionsField()">
<div ng-hide="specialInstructionsEditForm.$visible"
ng-class="{'image-info--multiple': ctrl.hasMultipleSpecialInstructions()}">

<dd ng-if="!ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
class="image-info__special-instructions"
>{{ctrl.metadata.specialInstructions}}
</dd>
</div>
<div ng-if="ctrl.userCanEdit">
<dd class="image-info__special-instructions"
ng-if="ctrl.hasMultipleSpecialInstructions()"
>Multiple special instructions (click ✎ to edit <strong>all</strong>)
</dd>

<div ng-if="!ctrl.userCanEdit">
<dd ng-if="ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
class="image-info__special-instructions"
>Multiple special instructions
</dd>
<dd class="image-info__special-instructions"
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
ng-if="!ctrl.hasMultipleSpecialInstructions() && !ctrl.metadata.usageInstructions"
>{{ctrl.metadata.specialInstructions || "Unknown (click ✎ to add)"}}
</dd>

<dd ng-if="!ctrl.hasMultipleValues(ctrl.rawMetadata.specialInstructions)"
class="image-info__special-instructions"
>{{ctrl.metadata.specialInstructions}}
</dd>
<dd class="image-info__special-instructions"
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
ng-if="!ctrl.hasMultipleSpecialInstructions() && ctrl.metadata.usageInstructions"
>{{ctrl.metadata.specialInstructions || "Click ✎ to add further instructions"}}
</dd>
</div>

<div ng-if="!ctrl.userCanEdit">
<dd class="image-info__special-instructions"
ng-if="ctrl.hasMultipleSpecialInstructions()"
>Multiple special instructions
</dd>

<dd class="image-info__special-instructions"
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
ng-if="!ctrl.hasMultipleSpecialInstructions() && ctrl.metadata.usageInstructions"
>{{ctrl.metadata.specialInstructions || ""}}
</dd>

<dd class="image-info__special-instructions"
ng-class="{'editable-empty': !ctrl.metadata.specialInstructions}"
ng-if="!ctrl.hasMultipleSpecialInstructions() && !ctrl.metadata.usageInstructions"
>{{ctrl.metadata.specialInstructions || "Unknown"}}
</dd>
</div>
</div>
<div
class="metadata-line__info"
editable-textarea="ctrl.metadata.specialInstructions"
ng-hide="specialInstructionsEditForm.$visible"
e:msd-elastic
e:ng-class="{'image-info__editor--error': $error,
'image-info__editor--saving': specialInstructionsEditForm.$waiting,
'text-input': true}"
>
</div>
</div>
<div ng-if="ctrl.userCanEdit && specialInstructionsEditForm.$visible" class="editable-buttons">
<button class="button-cancel" type="button" ng-click="specialInstructionsEditForm.$cancel()">
<gr-icon-label gr-icon="close">Cancel</gr-icon-label>
</button>
<button class="button-save" type="submit">
<gr-icon-label gr-icon="check">Save</gr-icon-label>
</button>
</div>
</form>
</span>
</dl>
</dl>
</div>

<div class="image-info__group" role="region" aria-label="Image metadata">
Expand Down
Loading

0 comments on commit 6387314

Please sign in to comment.