diff --git a/__tests__/end-to-end.js b/__tests__/end-to-end.js index 1e0104e29..0f4eba539 100644 --- a/__tests__/end-to-end.js +++ b/__tests__/end-to-end.js @@ -2776,6 +2776,10 @@ describe('end-to-end', () => { // wait for snapshots tab to load and publish snapshot await waitForAndClick('[data-test-id="publish-snapshot-button"]') + + // wait for snapshot export modal and click "no" to proprietary file export + await waitForAndClick('[data-test-id="export-patterns-modal-no"]') + // wait for version to get created await waitAndClearCompletedJobs() diff --git a/i18n/english.yml b/i18n/english.yml index 126c3df2a..77aef34fe 100644 --- a/i18n/english.yml +++ b/i18n/english.yml @@ -87,6 +87,9 @@ components: placeholder: Additional information (optional) publishNewVersion: label: Publish snapshot as new feed version + publishProprietaryFiles: + helpText: Proprietary files allow you to maintain certain Datatools features, such as pattern names, when re-importing a feed. + label: Publish new feed version with proprietary (extra) Datatools files. confirmPublishWithUnapproved: label: Confirm publish with unapproved routes unapprovedRoutesHeader: "The following routes are not approved" @@ -290,6 +293,7 @@ components: load: Load for Editing loadLatest: Load latest for editing name: Name + noOtherSnapshots: No other snapshots noSnapshotsExist: No snapshots currently exist for this feed. Snapshots can be created within the Editor. Click "Edit Feed" to enter editing mode. noVersions: (No Versions) noVersionsExist: No versions exist for this feed source. @@ -336,6 +340,10 @@ components: deleteRange: Delete range ExceptionValidationErrorsList: andOtherErrors: ...and %errors% other errors + ExportPatternsModal: + exportPatterns: Publish version with proprietary patterns? + no: No + yes: Yes FeedFetchFrequency: DAYS: days fetchFeedEvery: Fetch feed every diff --git a/i18n/german.yml b/i18n/german.yml index b8b2c3175..6a3d04ed0 100644 --- a/i18n/german.yml +++ b/i18n/german.yml @@ -80,6 +80,9 @@ components: placeholder: Name des Schnappschusses (erforderlich) publishNewVersion: label: Veröffentliche Schnappschuss als neue Feed-Version + publishProprietaryFiles: + helpText: Proprietary files allow you to maintain certain Datatools features, such as pattern names, when re-importing a feed. + label: Publish new feed version with proprietary (extra) Datatools files. missingNameAlert: Gültiger Schnappschuss-Name erforderlich! ok: OK title: Neuen Schnappschuss erstellen @@ -295,6 +298,7 @@ components: load: Zur Bearbeitung laden loadLatest: Aktuellsten zur Bearbeitung herunterladen name: Name + noOtherSnapshots: No other snapshots noSnapshotsExist: Für diese Feed-Quelle existieren noch keine Schnappschüsse. Schnappschüsse können im Editor erstellt werden. Wählen Sie "Feed bearbeiten" um den Bearbeitungsmodus zu starten. @@ -346,6 +350,10 @@ components: deleteRange: Delete range ExceptionValidationErrorsList: andOtherErrors: ...and %errors% other errors + ExportPatternsModal: + exportPatterns: Publish version with proprietary patterns? + no: No + yes: Yes FeedActionsDropdown: delete: Löschen deleteFeedSource: Feed-Quelle löschen? diff --git a/i18n/polish.yml b/i18n/polish.yml index b0f833b52..e88d759c3 100644 --- a/i18n/polish.yml +++ b/i18n/polish.yml @@ -79,6 +79,9 @@ components: placeholder: Nazwa migawki (wymagana) publishNewVersion: label: Publikuj migawkę jako nowa wersja pliku + publishProprietaryFiles: + helpText: Proprietary files allow you to maintain certain Datatools features, such as pattern names, when re-importing a feed. + label: Publish new feed version with proprietary (extra) Datatools files. missingNameAlert: Migawce należy nadać prawidłową nazwę! ok: OK title: Utwórz nową migawkę @@ -295,6 +298,7 @@ components: load: Wczytaj do edycji loadLatest: Załaduj najnowszy do edycji name: Nazwa + noOtherSnapshots: No other snapshots noSnapshotsExist: Obecnie nie istnieją żadne zrzuty tego kanału. Migawki można tworzyć w Edytorze. Kliknij „Edytuj kanał”, aby przejść do trybu edycji. noVersions: (Brak wersji) @@ -343,6 +347,10 @@ components: deleteRange: Delete range ExceptionValidationErrorsList: andOtherErrors: ...and %errors% other errors + ExportPatternsModal: + exportPatterns: Publish version with proprietary patterns? + no: No + yes: Yes FeedActionsDropdown: delete: Delete deleteFeedSource: Delete Feed Source? diff --git a/lib/common/components/ExportPatternsModal.js b/lib/common/components/ExportPatternsModal.js new file mode 100644 index 000000000..815606903 --- /dev/null +++ b/lib/common/components/ExportPatternsModal.js @@ -0,0 +1,69 @@ +// @flow + +import React from 'react' +import { Modal, Button } from 'react-bootstrap' + +import {getComponentMessages} from '../../common/util/config' +import * as versionActions from '../../manager/actions/versions' +import type { Feed, Snapshot } from '../../types' +import type { ItemProps } from '../../editor/components/EditorFeedSourcePanel' + +type Props = { + createFeedVersionFromSnapshot: typeof versionActions.createFeedVersionFromSnapshot, + feedSource: Feed, +} + +type State = { + showModal: boolean, + snapshot: ?Snapshot +} + +export default class ExportPatternsModal extends React.Component { + messages = getComponentMessages('ExportPatternsModal') + + state = { + showModal: false, + snapshot: null + } + + publish (publishProprietaryFiles: boolean) { + const { createFeedVersionFromSnapshot, feedSource } = this.props + this.state.snapshot && createFeedVersionFromSnapshot(feedSource, this.state.snapshot.id, publishProprietaryFiles) + this.close() + } + + close () { + this.setState({showModal: false}) + } + + // Open is called by the SnapshotItem class + open (props: ItemProps) { + this.setState({showModal: true, snapshot: props.snapshot}) + } + + render () { + const {Body, Title} = Modal + const buttonStyle = {marginLeft: '10px', width: '50px'} + + return ( + + + {this.messages('exportPatterns')} + + + + + ) + } +} diff --git a/lib/editor/actions/snapshots.js b/lib/editor/actions/snapshots.js index 70e695027..b7c45e7f0 100644 --- a/lib/editor/actions/snapshots.js +++ b/lib/editor/actions/snapshots.js @@ -5,7 +5,6 @@ import {createAction, type ActionType} from 'redux-actions' import {secureFetch} from '../../common/actions' import {getConfigProperty} from '../../common/util/config' import {handleJobResponse} from '../../manager/actions/status' - import type {Feed, Snapshot} from '../../types' import type {dispatchFn, getStateFn} from '../../types/reducers' @@ -87,9 +86,9 @@ export function downloadSnapshotViaCredentials (snapshot: Snapshot, isPublic: bo /** * Create a new snapshot from the data currently present in the editor buffer. */ -export function createSnapshot (feedSource: Feed, name: string, comment?: ?string, publishNewVersion?: boolean) { +export function createSnapshot (feedSource: Feed, name: string, comment?: ?string, publishNewVersion?: boolean, publishProprietaryFiles?: boolean) { return function (dispatch: dispatchFn, getState: getStateFn) { - const url = `/api/editor/secure/snapshot?feedId=${feedSource.id}${publishNewVersion ? '&publishNewVersion=true' : ''}` + const url = `/api/editor/secure/snapshot?feedId=${feedSource.id}${publishNewVersion ? '&publishNewVersion=true' : ''}${publishProprietaryFiles ? '&publishProprietaryFiles=true' : ''}` const snapshot = { feedId: feedSource.id, name, diff --git a/lib/editor/components/CreateSnapshotModal.js b/lib/editor/components/CreateSnapshotModal.js index 2c74f2d25..9fa9688fc 100644 --- a/lib/editor/components/CreateSnapshotModal.js +++ b/lib/editor/components/CreateSnapshotModal.js @@ -8,7 +8,9 @@ import { ControlLabel, FormGroup, FormControl, - Modal + Modal, + OverlayTrigger, + Tooltip } from 'react-bootstrap' import {connect} from 'react-redux' @@ -34,6 +36,7 @@ type State = { loading: boolean, name: ?string, publishNewVersion: boolean, + publishProprietaryFiles: boolean, showModal: boolean, } @@ -42,6 +45,7 @@ function getDefaultState () { comment: null, name: formatTimestamp(), publishNewVersion: false, + publishProprietaryFiles: false, confirmPublishWithUnapproved: false, showModal: false, loading: false @@ -54,6 +58,12 @@ class CreateSnapshotModal extends Component { messages = getComponentMessages('CreateSnapshotModal') _onTogglePublish = (e: SyntheticInputEvent) => { + // If unchecking publishNewVersion, we need to also uncheck publishProprietaryFiles + if (!e.target.checked) this.setState({publishProprietaryFiles: false}) + this.setState({[e.target.name]: e.target.checked}) + } + + _onTogglePublishProprietaryFiles = (e: SyntheticInputEvent) => { this.setState({[e.target.name]: e.target.checked}) } @@ -91,9 +101,9 @@ class CreateSnapshotModal extends Component { ok = () => { const {createSnapshot, feedSource} = this.props - const {comment, name, publishNewVersion} = this.state + const {comment, name, publishNewVersion, publishProprietaryFiles} = this.state if (!name) return window.alert(this.messages('missingNameAlert')) - createSnapshot(feedSource, name, comment, publishNewVersion) + createSnapshot(feedSource, name, comment, publishNewVersion, publishProprietaryFiles) this.close() } @@ -105,6 +115,7 @@ class CreateSnapshotModal extends Component { loading, name, publishNewVersion, + publishProprietaryFiles, showModal } = this.state const {routes} = this.props @@ -142,13 +153,27 @@ class CreateSnapshotModal extends Component { placeholder={this.messages('fields.comment.placeholder')} /> - + {this.messages('fields.publishNewVersion.label')} + {publishNewVersion && + {this.messages('fields.publishProprietaryFiles.helpText')}}> + + + {this.messages('fields.publishProprietaryFiles.label')} + + + + } {loading && } {unapprovedRoutes.length > 0 && diff --git a/lib/editor/components/EditorFeedSourcePanel.js b/lib/editor/components/EditorFeedSourcePanel.js index f1425a6cf..2ec08b3cd 100644 --- a/lib/editor/components/EditorFeedSourcePanel.js +++ b/lib/editor/components/EditorFeedSourcePanel.js @@ -8,6 +8,7 @@ import moment from 'moment' import * as snapshotActions from '../actions/snapshots.js' import ConfirmModal from '../../common/components/ConfirmModal' +import ExportPatternsModal from '../../common/components/ExportPatternsModal.js' import {getComponentMessages, getConfigProperty} from '../../common/util/config' import CreateSnapshotModal from '../../editor/components/CreateSnapshotModal' import * as versionActions from '../../manager/actions/versions' @@ -63,6 +64,11 @@ export default class EditorFeedSourcePanel extends Component { ref='snapshotModal' /> + {feedSource.editorSnapshots && feedSource.editorSnapshots.length ?
@@ -73,13 +79,13 @@ export default class EditorFeedSourcePanel extends Component { {snapshots.length === 0 - ? No other snapshots + ? {this.messages('noOtherSnapshots')} : snapshots.map(s => { return ( ) @@ -122,7 +128,7 @@ export default class EditorFeedSourcePanel extends Component { } } -type ItemProps = { +export type ItemProps = { createFeedVersionFromSnapshot: typeof versionActions.createFeedVersionFromSnapshot, deleteSnapshot: typeof snapshotActions.deleteSnapshot, disabled: boolean, @@ -142,8 +148,7 @@ class SnapshotItem extends Component { } _onClickExport = () => { - const {createFeedVersionFromSnapshot, feedSource, snapshot} = this.props - createFeedVersionFromSnapshot(feedSource, snapshot.id) + this.props.modal.open({snapshot: this.props.snapshot}) } _onDeleteSnapshot = () => { diff --git a/lib/manager/actions/versions.js b/lib/manager/actions/versions.js index a89fdb7df..fe0bc9d35 100644 --- a/lib/manager/actions/versions.js +++ b/lib/manager/actions/versions.js @@ -543,10 +543,11 @@ export function downloadFeedViaToken ( */ export function createFeedVersionFromSnapshot ( feedSource: Feed, - snapshotId: string + snapshotId: string, + publishProprietaryFiles: boolean ) { return function (dispatch: dispatchFn, getState: getStateFn) { - const url = `${SECURE_API_PREFIX}feedversion/fromsnapshot?feedSourceId=${feedSource.id}&snapshotId=${snapshotId}` + const url = `${SECURE_API_PREFIX}feedversion/fromsnapshot?feedSourceId=${feedSource.id}&snapshotId=${snapshotId}&publishProprietaryFiles=${publishProprietaryFiles.toString()}` return dispatch(secureFetch(url, 'post')) .then(res => dispatch(handleJobResponse(res, 'Error downloading snapshot'))) }