diff --git a/scripts/apps/archive/views/preview.html b/scripts/apps/archive/views/preview.html index deaf3c7b50..75e4f7c3e5 100644 --- a/scripts/apps/archive/views/preview.html +++ b/scripts/apps/archive/views/preview.html @@ -130,11 +130,17 @@
- +
+ ng-if="selected.preview.extra[field._id] && (field.field_type === 'text' || field.field_type === 'date' || field.field_type === 'urls')"> +
+
+ +
diff --git a/scripts/apps/authoring/authoring/article-url-fields.tsx b/scripts/apps/authoring/authoring/article-url-fields.tsx new file mode 100644 index 0000000000..22ebb789f0 --- /dev/null +++ b/scripts/apps/authoring/authoring/article-url-fields.tsx @@ -0,0 +1,82 @@ +import React from 'react'; + +interface IProps { + label: string; + urls: Array; + helperText: string; + fieldId: string; + onChange: (fieldId: string, urls: Array) => void; +} + +interface IState { + urls: Array; +} + +export class ArticleUrlFields extends React.Component { + constructor(props) { + super(props); + + // local state is used, because onChange is debounced + this.state = { + urls: Array.isArray(props.urls) && props.urls.length > 0 ? props.urls : [], + }; + } + removeUrl(index) { + this.setState({ + urls: this.state.urls.filter((_, i) => i !== index), + }, () => { + this.props.onChange(this.props.fieldId, this.state.urls); + }); + } + addUrl() { + this.setState({ + urls: this.state.urls.concat('https://'), + }, () => { + this.props.onChange(this.props.fieldId, this.state.urls); + }); + } + handleChange(index, event) { + const nextUrls = this.state.urls.map((currentValue, i) => { + if (i === index) { + return event.target.value; + } else { + return currentValue; + } + }); + + this.setState({ + urls: nextUrls, + }, () => { + this.props.onChange(this.props.fieldId, this.state.urls); + }); + } + render() { + const {label, helperText} = this.props; + + return ( +
+ + + {this.state.urls.map((url, i) => ( +
+ + +
+ ))} + +
+ +
+ + { + helperText == null ? null :
{helperText}
+ } +
+ ); + } +} diff --git a/scripts/apps/authoring/authoring/directives/ArticleEditDirective.js b/scripts/apps/authoring/authoring/directives/ArticleEditDirective.js index 0432e69ebd..63990709e5 100644 --- a/scripts/apps/authoring/authoring/directives/ArticleEditDirective.js +++ b/scripts/apps/authoring/authoring/directives/ArticleEditDirective.js @@ -63,6 +63,11 @@ export function ArticleEditDirective( templateUrl: 'scripts/apps/authoring/views/article-edit.html', link: function(scope, elem) { getLabelNameResolver().then((getLabelForFieldId) => { + scope.handleUrlsChange = function(fieldId, value) { + scope.item.extra[fieldId] = value; + scope.autosave(scope.item); + }; + scope.toggleDetails = true; scope.errorMessage = null; scope.contentType = null; diff --git a/scripts/apps/authoring/authoring/index.ts b/scripts/apps/authoring/authoring/index.ts index 228815a78d..50e9a51fb4 100644 --- a/scripts/apps/authoring/authoring/index.ts +++ b/scripts/apps/authoring/authoring/index.ts @@ -7,6 +7,8 @@ import * as filter from './filters'; import '../suggest'; import mediaModule from '../media'; +import {reactToAngular1} from 'superdesk-ui-framework'; +import {ArticleUrlFields} from './article-url-fields'; angular.module('superdesk.apps.authoring.autosave', []).service('autosave', svc.AutosaveService); @@ -76,6 +78,9 @@ angular.module('superdesk.apps.authoring', [ .directive('sdRemoveTags', directive.RemoveTagsDirective) .directive('tansaScopeSync', directive.TansaScopeSyncDirective) .directive('sdItemActionByIntent', directive.ItemActionsByIntentDirective) + .component('sdArticleUrlFields', + reactToAngular1(ArticleUrlFields, ['label', 'urls', 'helperText', 'onChange', 'fieldId']), + ) .filter('embeddedFilter', filter.EmbeddedFilter) diff --git a/scripts/apps/authoring/views/article-edit.html b/scripts/apps/authoring/views/article-edit.html index 3a93cead31..792b1b063a 100644 --- a/scripts/apps/authoring/views/article-edit.html +++ b/scripts/apps/authoring/views/article-edit.html @@ -674,3 +674,19 @@
{{field.helper_text}}
+ + +
+ + +
diff --git a/scripts/apps/vocabularies/controllers/VocabularyConfigController.ts b/scripts/apps/vocabularies/controllers/VocabularyConfigController.ts index 0175a89b1b..12347da6ed 100644 --- a/scripts/apps/vocabularies/controllers/VocabularyConfigController.ts +++ b/scripts/apps/vocabularies/controllers/VocabularyConfigController.ts @@ -86,6 +86,7 @@ export function VocabularyConfigController($scope: IScope, $route, $routeParams, tab === 'vocabularies' && !fieldType || fieldType && (tab === 'text-fields' && fieldType === 'text' || tab === 'date-fields' && fieldType === 'date' || + tab === 'urls-fields' && fieldType === 'urls' || tab === 'related-content-fields' && MEDIA_TYPE_KEYS.includes(fieldType) || tab === 'embed-fields' && fieldType === 'embed'); diff --git a/scripts/apps/vocabularies/views/settings.html b/scripts/apps/vocabularies/views/settings.html index a949b15965..d7aabf43ce 100644 --- a/scripts/apps/vocabularies/views/settings.html +++ b/scripts/apps/vocabularies/views/settings.html @@ -21,6 +21,9 @@

Metadata management

  • +
  • + +
  • diff --git a/scripts/apps/vocabularies/views/vocabulary-config.html b/scripts/apps/vocabularies/views/vocabulary-config.html index ea21e9fc05..4b0b3ab121 100644 --- a/scripts/apps/vocabularies/views/vocabulary-config.html +++ b/scripts/apps/vocabularies/views/vocabulary-config.html @@ -31,6 +31,12 @@ Add New + +
    diff --git a/scripts/apps/workspace/content/services/ContentService.js b/scripts/apps/workspace/content/services/ContentService.js index 6ed570a73a..da225199e6 100644 --- a/scripts/apps/workspace/content/services/ContentService.js +++ b/scripts/apps/workspace/content/services/ContentService.js @@ -320,7 +320,7 @@ export function ContentService(api, superdesk, templates, desks, packages, archi self._fieldsPromise = api.getAll('vocabularies', { where: { $or: [ - {field_type: {$in: ['text', 'date', 'media', 'embed']}}, + {field_type: {$in: ['text', 'date', 'media', 'embed', 'urls']}}, {service: {$exists: true}}, ], },