diff --git a/kahuna/public/js/components/gr-add-label/gr-add-label.js b/kahuna/public/js/components/gr-add-label/gr-add-label.js
index e4e0dcc706..e4ef83f22f 100644
--- a/kahuna/public/js/components/gr-add-label/gr-add-label.js
+++ b/kahuna/public/js/components/gr-add-label/gr-add-label.js
@@ -15,8 +15,8 @@ export var addLabel = angular.module('gr.addLabel', [
]);
addLabel.controller('GrAddLabelCtrl', [
- '$window', '$q', 'labelService', 'mediaApi',
- function ($window, $q, labelService, mediaApi) {
+ '$scope', '$window', '$q', 'labelService', 'mediaApi',
+ function ($scope, $window, $q, labelService, mediaApi) {
let ctrl = this;
@@ -42,7 +42,10 @@ addLabel.controller('GrAddLabelCtrl', [
reset();
})
.catch(saveFailed)
- .finally(() => ctrl.adding = false);
+ .finally(() => {
+ ctrl.adding = false;
+ $scope.$apply();
+ });
}
diff --git a/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.html b/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.html
index 78a58b1d5b..37bf72995c 100644
--- a/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.html
+++ b/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.html
@@ -358,8 +358,8 @@
-
People
-
+ People
+
@@ -449,22 +448,12 @@
-
-
- {{label.data}}
-
-
+
+
@@ -494,12 +483,11 @@
Keywords
diff --git a/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.js b/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.js
index e45a3b71eb..618c48179f 100644
--- a/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.js
+++ b/kahuna/public/js/components/gr-image-metadata/gr-image-metadata.js
@@ -6,7 +6,7 @@ import template from './gr-image-metadata.html';
import '../../image/service';
import '../../edits/service';
import '../gr-description-warning/gr-description-warning';
-import { editOptions, overwrite } from '../../util/constants/editOptions';
+import { editOptions, overwrite, append } from '../../util/constants/editOptions';
import '../../services/image-accessor';
import '../../services/image-list';
import '../../services/label';
@@ -100,15 +100,39 @@ module.controller('grImageMetadataCtrl', [
);
};
- ctrl.addLabel = function (label) {
- var imageArray = Array.from(ctrl.selectedImages);
- labelService.batchAdd(imageArray, [label]);
+ ctrl.addLabelToImages = labelService.batchAdd;
+ ctrl.removeLabelFromImages = labelService.batchRemove;
+ ctrl.labelAccessor = (image) => imageAccessor.readLabels(image).map(label => label.data);
+
+ ctrl.peopleAccessor = (image) => imageAccessor.readPeopleInImage(image);
+ ctrl.removePersonFromImages = (images, removedPerson) => {
+ images.map((image) => {
+ const maybeNewPeopleInImage = ctrl.peopleAccessor(image)?.filter((person) => person !== removedPerson);
+ const newPeopleInImage = maybeNewPeopleInImage ? maybeNewPeopleInImage : [];
+ editsService.batchUpdateMetadataField(
+ [image],
+ 'peopleInImage',
+ newPeopleInImage,
+ ctrl.descriptionOption
+ );
+ });
+ return Promise.resolve(ctrl.selectedImages);
};
+ ctrl.addPersonToImages = (images, addedPerson) => {
+ images.map((image) => {
+ const currentPeopleInImage = ctrl.peopleAccessor(image);
+ const newPeopleInImage = currentPeopleInImage ? [...currentPeopleInImage, addedPerson] : [addedPerson];
+ editsService.batchUpdateMetadataField(
+ [image],
+ 'peopleInImage',
+ newPeopleInImage,
+ ctrl.descriptionOption
+ );
+ });
+ return Promise.resolve(ctrl.selectedImages);
+ }
- ctrl.removeLabel = function (label) {
- var imageArray = Array.from(ctrl.selectedImages);
- labelService.batchRemove(imageArray, label);
- };
+ ctrl.keywordAccessor = (image) => imageAccessor.readMetadata(image).keywords;
const ignoredMetadata = [
'title', 'description', 'copyright', 'keywords', 'byline',
diff --git a/kahuna/public/js/edits/image-editor.html b/kahuna/public/js/edits/image-editor.html
index 34fe919bb2..b7d251e0e9 100644
--- a/kahuna/public/js/edits/image-editor.html
+++ b/kahuna/public/js/edits/image-editor.html
@@ -207,10 +207,13 @@ Organisation and Grouping
active="ctrl.inputtingLabel"
class="result-editor__field-container__add-button">
-
-
+
+
diff --git a/kahuna/public/js/edits/image-editor.js b/kahuna/public/js/edits/image-editor.js
index 44c92112e9..5b65cd1324 100644
--- a/kahuna/public/js/edits/image-editor.js
+++ b/kahuna/public/js/edits/image-editor.js
@@ -4,16 +4,22 @@ import './image-editor.css';
import {service} from './service';
import {imageService} from '../image/service';
+import '../services/label';
+import {imageAccessor} from '../services/image-accessor'
import {usageRightsEditor} from '../usage-rights/usage-rights-editor';
import {leases} from '../leases/leases';
import {archiver} from '../components/gr-archiver-status/gr-archiver-status';
import {collectionsApi} from '../services/api/collections-api';
import {rememberScrollTop} from '../directives/gr-remember-scroll-top';
+import {List} from 'immutable';
+
export var imageEditor = angular.module('kahuna.edits.imageEditor', [
service.name,
imageService.name,
+ "kahuna.services.label",
+ imageAccessor.name,
usageRightsEditor.name,
archiver.name,
collectionsApi.name,
@@ -28,6 +34,8 @@ imageEditor.controller('ImageEditorCtrl', [
'editsService',
'editsApi',
'imageService',
+ 'labelService',
+ 'imageAccessor',
'collections',
function($rootScope,
@@ -36,6 +44,8 @@ imageEditor.controller('ImageEditorCtrl', [
editsService,
editsApi,
imageService,
+ labelService,
+ imageAccessor,
collections) {
var ctrl = this;
@@ -56,6 +66,11 @@ imageEditor.controller('ImageEditorCtrl', [
ctrl.invalidReasons = ctrl.image.data.invalidReasons;
ctrl.systemName = window._clientConfig.systemName;
+ ctrl.addLabelToImages = labelService.batchAdd;
+ ctrl.removeLabelFromImages = labelService.batchRemove;
+ ctrl.labelAccessor = (image) => imageAccessor.readLabels(image).map(label => label.data);
+ ctrl.labelSref = (element) => {debugger; return search.results({query:(element | queryLabelFilter)})};
+
//TODO put collections in their own directive
ctrl.addCollection = false;
ctrl.addToCollection = addToCollection;
diff --git a/kahuna/public/js/edits/index.js b/kahuna/public/js/edits/index.js
index 95040f8f08..6913ff8adf 100644
--- a/kahuna/public/js/edits/index.js
+++ b/kahuna/public/js/edits/index.js
@@ -1,7 +1,7 @@
import angular from 'angular';
-import './labeller';
+import './list-editor';
export var edits = angular.module('kahuna.edits', [
- 'kahuna.edits.labeller'
+ 'kahuna.edits.listEditor'
]);
diff --git a/kahuna/public/js/edits/list-editor-compact.html b/kahuna/public/js/edits/list-editor-compact.html
new file mode 100644
index 0000000000..e2c59cdc86
--- /dev/null
+++ b/kahuna/public/js/edits/list-editor-compact.html
@@ -0,0 +1,16 @@
+
+
+ -
+
+ {{element}}
+
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ {{ctrl.sref(element)}}
+
+ {{element}}
+
+
+
+
diff --git a/kahuna/public/js/edits/list-editor-info-panel.html b/kahuna/public/js/edits/list-editor-info-panel.html
new file mode 100644
index 0000000000..3ff63cd2d8
--- /dev/null
+++ b/kahuna/public/js/edits/list-editor-info-panel.html
@@ -0,0 +1,16 @@
+
+
+ {{element.data}}
+
+
diff --git a/kahuna/public/js/edits/list-editor-upload.html b/kahuna/public/js/edits/list-editor-upload.html
new file mode 100644
index 0000000000..0928275c26
--- /dev/null
+++ b/kahuna/public/js/edits/list-editor-upload.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
diff --git a/kahuna/public/js/edits/list-editor.css b/kahuna/public/js/edits/list-editor.css
new file mode 100644
index 0000000000..0bc5766fee
--- /dev/null
+++ b/kahuna/public/js/edits/list-editor.css
@@ -0,0 +1,93 @@
+ui-list-editor,
+ui-list-editor-compact {
+ display: block;
+}
+
+.labeller {
+ font-size: 1.3rem;
+ display: flex;
+}
+
+.element {
+ color: white;
+ display: inline-flex;
+ justify-content: space-between;
+ margin: 0 5px 5px 0;
+}
+
+.element--removing {
+ background-color: #99ddff;
+}
+
+/*
+element--partial is part of gr-panel.
+*/
+.element--partial .element__value,
+.element--partial .element__add,
+.element--partial .element__remove {
+ background-color: white;
+ color: #00adee;
+}
+
+.element__value,
+.element__remove {
+ color: white;
+ background-color: #00adee;
+}
+
+.element__link:hover,
+.element__remove:hover {
+ color: #00adee;
+ background-color: white;
+}
+
+.element__add,
+.element__value {
+ border-top-left-radius: 2px;
+ border-bottom-left-radius: 2px;
+}
+
+.element--partial .element__value {
+ border-radius: 0px;
+}
+
+.element__value {
+ padding: 0 5px;
+}
+
+.element__value--compact {
+ border-radius: 2px;
+}
+
+.element__remove {
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+
+.element button:hover gr-icon {
+ color: #333;
+}
+
+.element button:active gr-icon {
+ background-color: #008fc5;
+ color: #333;
+}
+
+.element--partial button:active gr-icon {
+ background-color: #CFCFCF;
+ color: #333;
+}
+
+.labeller__apply-all {
+ margin-left: 10px;
+ line-height: 20px;
+ font-size: 1.6rem;
+}
+
+.labeller__apply-all:hover {
+ color: #FFF;
+}
+
+.image-info__keyword .element__value {
+ background-color: #222;
+}
\ No newline at end of file
diff --git a/kahuna/public/js/edits/list-editor.js b/kahuna/public/js/edits/list-editor.js
new file mode 100644
index 0000000000..c0b3909f9a
--- /dev/null
+++ b/kahuna/public/js/edits/list-editor.js
@@ -0,0 +1,176 @@
+import angular from 'angular';
+import templateUpload from './list-editor-upload.html';
+import templateCompact from './list-editor-compact.html';
+import templateInfoPanel from './list-editor-info-panel.html';
+import {List} from 'immutable';
+import './list-editor.css';
+import '../services/image-list';
+
+import '../search/query-filter';
+
+export var listEditor = angular.module('kahuna.edits.listEditor', [
+ 'kahuna.search.filters.query',
+ 'kahuna.services.image-logic',
+]);
+
+listEditor.controller('ListEditorCtrl', [
+ '$rootScope',
+ '$scope',
+ '$window',
+ '$timeout',
+ 'imageLogic',
+ 'imageList',
+ function($rootScope,
+ $scope,
+ $window,
+ $timeout,
+ imageLogic,
+ imageList) {
+ var ctrl = this;
+// debugger;
+// ctrl.sref("test-sref")
+
+
+ const retrieveElementsWithOccurrences = (images) => imageList.getOccurrences(images.flatMap(img => ctrl.accessor(img)));
+
+ $scope.$watchCollection('ctrl.images', updatedImages => updateHandler(updatedImages));
+
+ const updateHandler = (maybeUpdatedImages) => {
+ const updatedImages = ctrl.images.map(img => maybeUpdatedImages.find(x => imageLogic.isSameImage(x, img)) || img);
+ ctrl.listWithOccurrences = retrieveElementsWithOccurrences(updatedImages);
+ ctrl.plainList = ctrl.listWithOccurrences.map(x => x.data);
+
+ };
+
+ const updateListener = $rootScope.$on('images-updated', (e, updatedImages) => {
+ updateHandler(updatedImages);
+ });
+
+ ctrl.listWithOccurrences = retrieveElementsWithOccurrences(ctrl.images);
+ ctrl.plainList = ctrl.listWithOccurrences.map(x => x.data);
+
+ function saveFailed(e) {
+ console.error(e);
+ $window.alert('Something went wrong when saving, please try again!');
+ }
+
+ ctrl.addElements = elements => {
+ ctrl.adding = true;
+
+ ctrl.addToImages(ctrl.images, elements)
+ .then(imgs => {
+ updateHandler(imgs);
+ })
+ .catch(saveFailed)
+ .finally(() => {
+ ctrl.adding = false;
+ });
+ };
+
+ ctrl.elementsBeingRemoved = new Set();
+ ctrl.removeElement = element => {
+ ctrl.elementsBeingRemoved.add(element);
+
+ ctrl.removeFromImages(ctrl.images, element)
+ .then(imgs => {
+ updateHandler(imgs);
+ })
+ .catch(saveFailed)
+ .finally(() => {
+ ctrl.elementsBeingRemoved.delete(element);
+ });
+ };
+
+ ctrl.removeAll = () => {
+ ctrl.plainList.forEach(element => ctrl.removeFromImages(ctrl.images, element));
+ };
+
+ const batchAddEvent = 'events:batch-apply:add-all';
+ const batchRemoveEvent = 'events:batch-apply:remove-all';
+
+ if (Boolean(ctrl.withBatch)) {
+ $scope.$on(batchAddEvent, (e, elements) => ctrl.addElements(elements));
+ $scope.$on(batchRemoveEvent, () => ctrl.removeAll());
+
+ ctrl.batchApply = () => {
+ var elements = ctrl.plainList;
+
+ if (elements.length > 0) {
+ $rootScope.$broadcast(batchAddEvent, elements);
+ } else {
+ ctrl.confirmDelete = true;
+
+ $timeout(() => {
+ ctrl.confirmDelete = false;
+ }, 5000);
+ }
+ };
+
+ ctrl.batchRemove = () => {
+ ctrl.confirmDelete = false;
+ $rootScope.$broadcast(batchRemoveEvent);
+ };
+ }
+
+ $scope.$on('$destroy', function() {
+ updateListener();
+ });
+}]);
+
+listEditor.directive('uiListEditorUpload', [function() {
+ return {
+ restrict: 'E',
+ scope: {
+ // Annoying that we can't make a uni-directional binding
+ // as we don't really want to modify the original
+ images: '<',
+ withBatch: '=?',
+ addToImages: '=',
+ removeFromImages: '=',
+ accessor: '='
+ },
+ controller: 'ListEditorCtrl',
+ controllerAs: 'ctrl',
+ bindToController: true,
+ template: templateUpload
+ };
+}]);
+
+listEditor.directive('uiListEditorCompact', [function() {
+ return {
+ restrict: 'E',
+ scope: {
+ // Annoying that we can't make a uni-directional binding
+ // as we don't really want to modify the original
+ images: '<',
+ disabled: '=',
+ removeFromImages: '=',
+ accessor: '=',
+ sref: '=',
+ element: '='
+ },
+ controller: 'ListEditorCtrl',
+ controllerAs: 'ctrl',
+ bindToController: true,
+ template: templateCompact
+ };
+}]);
+
+listEditor.directive('uiListEditorInfoPanel', [function() {
+ return {
+ restrict: 'E',
+ scope: {
+ // Annoying that we can't make a uni-directional binding
+ // as we don't really want to modify the original
+ images: '<',
+ disabled: '<',
+ addToImages: '<',
+ removeFromImages: '<',
+ accessor: '<'
+ },
+ controller: 'ListEditorCtrl',
+ controllerAs: 'ctrl',
+ bindToController: true,
+ template: templateInfoPanel
+ };
+}]);
diff --git a/kahuna/public/js/preview/image-large.html b/kahuna/public/js/preview/image-large.html
index 25a7e04e49..c47fe86556 100644
--- a/kahuna/public/js/preview/image-large.html
+++ b/kahuna/public/js/preview/image-large.html
@@ -70,15 +70,20 @@
-
-
+ ng-if="!ctrl.inputtingLabel"
+ add-to-images="ctrl.addLabelToImages"
+ remove-from-images="ctrl.removeLabelFromImages"
+ element="ctrl.xyz"
+ accessor="ctrl.labelAccessor"
+ sref="ctrl.labelSref">
+
diff --git a/kahuna/public/js/preview/image.html b/kahuna/public/js/preview/image.html
index 433ec5e8cd..02dd191adc 100644
--- a/kahuna/public/js/preview/image.html
+++ b/kahuna/public/js/preview/image.html
@@ -62,15 +62,19 @@
-
-
+ ng-if="!ctrl.inputtingLabel"
+ add-to-images="ctrl.addLabelToImages"
+ remove-from-images="ctrl.removeLabelFromImages"
+ accessor="ctrl.labelAccessor"
+ sref="ctrl.labelSref">
+
diff --git a/kahuna/public/js/preview/image.js b/kahuna/public/js/preview/image.js
index 5ce7f15fd4..0d8ed95f0d 100644
--- a/kahuna/public/js/preview/image.js
+++ b/kahuna/public/js/preview/image.js
@@ -6,16 +6,24 @@ import '../util/rx';
import template from './image.html';
import templateLarge from './image-large.html';
+import '../search/query-filter';
+
+import {List} from 'immutable';
import '../image/service';
import '../imgops/service';
import '../services/image/usages';
+import '../services/label';
+import '../services/image-accessor';
import '../components/gr-add-label/gr-add-label';
import '../components/gr-archiver-status/gr-archiver-status';
import '../components/gr-syndication-icon/gr-syndication-icon';
export var image = angular.module('kahuna.preview.image', [
+ 'kahuna.search.filters.query',
'gr.image.service',
'gr.image-usages.service',
+ 'kahuna.services.label',
+ 'kahuna.services.image-accessor',
'gr.addLabel',
'gr.archiverStatus',
'gr.syndicationIcon',
@@ -30,19 +38,40 @@ image.controller('uiPreviewImageCtrl', [
'$window',
'imageService',
'imageUsagesService',
+ 'labelService',
+ 'imageAccessor',
function (
$scope,
inject$,
$rootScope,
$window,
imageService,
- imageUsagesService) {
+ imageUsagesService,
+ labelService,
+ imageAccessor) {
var ctrl = this;
+ $scope.$watch(() => ctrl.image, (newImage) => {
+ ctrl.imageAsArray = [newImage];
+ })
+
+ ctrl.addLabelToImages = labelService.batchAdd;
+ ctrl.removeLabelFromImages = labelService.batchRemove;
+ ctrl.labelAccessor = (image) => imageAccessor.readLabels(image).map(label => label.data);
+ ctrl.labelSref = (element) => {
+ console.log("***********image.js ctrl.labelSref *************")
+ console.log(element)
+// debugger;
+ const result = `(${element} | queryLabelFilter)`
+ return result
+ };
+ ctrl.imageAsArray = [ctrl.image];
+
const updateImage = (updatedImage) => {
ctrl.states = imageService(updatedImage).states;
ctrl.image = updatedImage;
ctrl.flagState = ctrl.states.costState;
+ ctrl.imageAsArray = [updatedImage];
};
const freeImagesUpdateListener = $rootScope.$on('images-updated', (e, updatedImages) => {
diff --git a/kahuna/public/js/search/query-filter.js b/kahuna/public/js/search/query-filter.js
index a9ff57c3a2..200525c902 100644
--- a/kahuna/public/js/search/query-filter.js
+++ b/kahuna/public/js/search/query-filter.js
@@ -3,7 +3,7 @@ import angular from 'angular';
import {getCollection} from '../search-query/query-syntax';
export var queryFilters = angular.module('kahuna.search.filters.query', []);
-
+debugger;
var containsSpace = s => / /.test(s);
var stripDoubleQuotes = s => s.replace(/"/g, '');
@@ -14,7 +14,6 @@ export function maybeQuoted(value) {
return value;
}
}
-
export function fieldFilter(field, value) {
const cleanValue = stripDoubleQuotes(value);
const valueMaybeQuoted = maybeQuoted(cleanValue);
@@ -22,10 +21,12 @@ export function fieldFilter(field, value) {
}
queryFilters.filter('queryFilter', function() {
+ debugger;
return (value, field) => fieldFilter(field, value);
});
queryFilters.filter('queryLabelFilter', function() {
+ debugger;
return (value) => {
const cleanValue = stripDoubleQuotes(value);
if (containsSpace(cleanValue)) {
diff --git a/kahuna/public/js/services/image-accessor.js b/kahuna/public/js/services/image-accessor.js
index ba833deee2..b226600da8 100644
--- a/kahuna/public/js/services/image-accessor.js
+++ b/kahuna/public/js/services/image-accessor.js
@@ -15,6 +15,9 @@ imageAccessor.factory('imageAccessor', function() {
/* == Readers == (return data) */
+ function readId(image) {
+ return image.data.id;
+ }
function readCost(image) {
return image.data.cost;
@@ -25,6 +28,10 @@ imageAccessor.factory('imageAccessor', function() {
return userMetadata.data.labels.data;
}
+ function readPeopleInImage(image) {
+ return image.data.metadata.peopleInImage;
+ }
+
function readLeases(image) {
return image.data.leases.data;
}
@@ -80,6 +87,7 @@ imageAccessor.factory('imageAccessor', function() {
}
return {
+ readId,
readCost,
readLabels,
readLeases,
@@ -87,6 +95,7 @@ imageAccessor.factory('imageAccessor', function() {
readExtraInfo,
readUsageRights,
readPersistedReasons,
+ readPeopleInImage,
isPersisted,
isArchived,
readCollections,
diff --git a/kahuna/public/js/services/image-logic.js b/kahuna/public/js/services/image-logic.js
index d39d1d0dbe..eebb38fe09 100644
--- a/kahuna/public/js/services/image-logic.js
+++ b/kahuna/public/js/services/image-logic.js
@@ -11,6 +11,10 @@ export const imageLogic = angular.module('kahuna.services.image-logic', [
*/
imageLogic.factory('imageLogic', ['imageAccessor', function(imageAccessor) {
+ function isSameImage(image1, image2) {
+ return imageAccessor.readId(image1) === imageAccessor.readId(image2);
+ }
+
function canBeDeleted(image) {
return image.getAction('delete').then(action => !! action);
}
@@ -101,6 +105,7 @@ imageLogic.factory('imageLogic', ['imageAccessor', function(imageAccessor) {
}
return {
+ isSameImage,
canBeDeleted,
canBeArchived,
getArchivedState,
diff --git a/kahuna/public/stylesheets/main.css b/kahuna/public/stylesheets/main.css
index 0d828d8fdb..eb947ef1d6 100644
--- a/kahuna/public/stylesheets/main.css
+++ b/kahuna/public/stylesheets/main.css
@@ -1696,7 +1696,7 @@ FIXME: what to do with touch devices
float: left;
}
-.image-info__keyword {
+.image-info__keyword li {
display: inline-block;
background-color: #222;
color: #999;
@@ -1707,7 +1707,7 @@ FIXME: what to do with touch devices
font-size: 1.3rem;
}
-.image-info__keyword a {
+.image-info__keyword li a {
color: inherit;
}
@@ -2413,7 +2413,7 @@ FIXME: what to do with touch devices
.image-info__description,
.image-info__special-instructions,
.label__value,
- .image-info__keyword {
+ .image-info__keyword li {
color: black !important;
}
@@ -2434,7 +2434,7 @@ FIXME: what to do with touch devices
width: auto;
}
- .image-info__description, .image-info__keyword {
+ .image-info__description, .image-info__keyword li {
max-height: 80px;
overflow: hidden;
}