diff --git a/app/addons/components/__tests__/apilinks.test.js b/app/addons/components/__tests__/apilinks.test.js new file mode 100644 index 000000000..75dfe15ae --- /dev/null +++ b/app/addons/components/__tests__/apilinks.test.js @@ -0,0 +1,37 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +import { JSONLink, DocLink } from "../components/apibar"; +import { mount } from "enzyme"; +import React from "react"; +import ReactDOM from "react-dom"; + +describe('JSONLink', () => { + + it('Should render with url', () => { + const url = "http://couchdb.com/_all_dbs"; + const el = mount(); + + expect(el.find('a').prop('href')).toEqual(url); + }); + +}); + +describe('DocLink', () => { + + it('Should render with url', () => { + const url = "http://couchdb.com/help/_all_dbs"; + const el = mount(); + + expect(el.find('a').prop('href')).toEqual(url); + }); + +}); diff --git a/app/addons/components/actions.js b/app/addons/components/actions.js index 8fb6593bf..2e8ae4e9a 100644 --- a/app/addons/components/actions.js +++ b/app/addons/components/actions.js @@ -13,28 +13,6 @@ import FauxtonAPI from "../../core/api"; import ActionTypes from "./actiontypes"; -function showAPIBarButton () { - FauxtonAPI.dispatch({ type: ActionTypes.CMPNTS_SHOW_API_BAR_BUTTON }); -} - -function hideAPIBarButton () { - FauxtonAPI.dispatch({ type: ActionTypes.CMPNTS_HIDE_API_BAR_BUTTON }); -} - -function toggleApiBarVisibility (visible) { - FauxtonAPI.dispatch({ - type: ActionTypes.CMPNTS_SET_API_BAR_CONTENT_VISIBLE_STATE, - options: visible - }); -} - -function updateAPIBar (params) { - FauxtonAPI.dispatch({ - type: ActionTypes.CMPNTS_UPDATE_API_BAR, - options: params - }); -} - function showDeleteDatabaseModal (options) { FauxtonAPI.dispatch({ type: ActionTypes.CMPNTS_DATABASES_SHOWDELETE_MODAL, @@ -72,9 +50,5 @@ function deleteDatabase (dbId) { export default { deleteDatabase: deleteDatabase, - showDeleteDatabaseModal: showDeleteDatabaseModal, - showAPIBarButton: showAPIBarButton, - hideAPIBarButton: hideAPIBarButton, - toggleApiBarVisibility: toggleApiBarVisibility, - updateAPIBar: updateAPIBar, + showDeleteDatabaseModal: showDeleteDatabaseModal }; diff --git a/app/addons/components/actiontypes.js b/app/addons/components/actiontypes.js index c349806a5..d9e718371 100644 --- a/app/addons/components/actiontypes.js +++ b/app/addons/components/actiontypes.js @@ -11,9 +11,5 @@ // the License. export default { - CMPNTS_SHOW_API_BAR_BUTTON: 'CMPNTS_SHOW_API_BAR_BUTTON', - CMPNTS_HIDE_API_BAR_BUTTON: 'CMPNTS_HIDE_API_BAR_BUTTON', - CMPNTS_UPDATE_API_BAR: 'CMPNTS_UPDATE_API_BAR', - CMPNTS_SET_API_BAR_CONTENT_VISIBLE_STATE: 'CMPNTS_SET_API_BAR_CONTENT_VISIBLE_STATE', - CMPNTS_DATABASES_SHOWDELETE_MODAL: 'CMPNTS_DATABASES_SHOWDELETE_MODAL', + CMPNTS_DATABASES_SHOWDELETE_MODAL: 'CMPNTS_DATABASES_SHOWDELETE_MODAL' }; diff --git a/app/addons/components/assets/less/components.less b/app/addons/components/assets/less/components.less index 53e15debe..9a0df82df 100644 --- a/app/addons/components/assets/less/components.less +++ b/app/addons/components/assets/less/components.less @@ -24,3 +24,4 @@ @import "header-breadcrumbs.less"; @import "layouts.less"; @import "polling.less"; +@import "jsonlink.less"; diff --git a/app/addons/components/assets/less/jsonlink.less b/app/addons/components/assets/less/jsonlink.less new file mode 100644 index 000000000..285df498c --- /dev/null +++ b/app/addons/components/assets/less/jsonlink.less @@ -0,0 +1,62 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +.faux__jsonlink { + width: 76px; + border-left: 1px solid #ccc; + padding: 16px 12px 12px 12px !important; + height: 64px; + background-color: rgba(0, 0, 0, 0); +} + +.faux__jsonlink-link { + color: #666; + text-decoration: none; + line-height: 33px; + font-size: 13px; +} + +.faux__jsonlink-link:visited, +.faux__jsonlink-link:focus, +.faux__jsonlink-link:active { + text-decoration: none; + color: #666; +} + +.faux__jsonlink-link-brackets { + font-size: 15px; + padding-right: 3px; + font-weight: 500; +} + +.faux__doclink { + text-align: center; + width: 55px; + border-left: 1px solid #ccc; + padding: 18px 12px 12px 12px !important; + height: 64px; + background-color: rgba(0, 0, 0, 0); +} + +.faux__doclink-link { + color: #666; + text-decoration: none; + line-height: 33px; + font-size: 20px; +} + +.faux__doclink-link:active, +.faux__doclink-link:focus, +.faux__doclink-link:visited { + text-decoration: none; + color: #666; +} diff --git a/app/addons/components/assets/less/layouts.less b/app/addons/components/assets/less/layouts.less index 99c17302f..4f020cf17 100644 --- a/app/addons/components/assets/less/layouts.less +++ b/app/addons/components/assets/less/layouts.less @@ -27,3 +27,7 @@ div.faux__breadcrumbs-mango-header { flex: 0 0 440px !important; overflow: hidden !important; } + +div.faux__jsondoc-wrapper { + display:flex; +} diff --git a/app/addons/components/components/apibar.js b/app/addons/components/components/apibar.js index e51e41851..e44f90574 100644 --- a/app/addons/components/components/apibar.js +++ b/app/addons/components/components/apibar.js @@ -12,125 +12,32 @@ import React from "react"; import ReactDOM from "react-dom"; -import FauxtonAPI from "../../../core/api"; -import {TrayContents, TrayWrapper, connectToStores} from './tray'; -import { Copy } from "./copy"; -import Actions from "../actions"; -import Stores from "../stores"; -import {ToggleHeaderButton} from './toggleheaderbutton'; -const { componentStore } = Stores; -import uuid from 'uuid'; -export const APIBar = React.createClass({ - propTypes: { - buttonVisible: React.PropTypes.bool.isRequired, - contentVisible: React.PropTypes.bool.isRequired, - docURL: React.PropTypes.string, - endpoint: React.PropTypes.string - }, - - showCopiedMessage () { - FauxtonAPI.addNotification({ - msg: 'The API URL has been copied to the clipboard.', - type: 'success', - clear: true - }); - }, +export const JSONLink = ({endpoint}) => { + if (!endpoint) { + return null; + } - getDocIcon () { - if (!this.props.docURL) { - return null; - } - return ( - - + return ( +
+ + {'{ '}{'}'} + JSON - ); - }, - - getTray () { - const {endpoint} = this.props; - return ( - -
- - API URL - {this.getDocIcon()} - - - - - -
-
- ); - }, - - toggleTrayVisibility () { - Actions.toggleApiBarVisibility(!this.props.contentVisible); - }, +
+ ); +}; - closeTray () { - Actions.toggleApiBarVisibility(false); - }, - - render () { - if (!this.props.buttonVisible || !this.props.endpoint) { - return null; - } - - return ( -
- - {this.getTray()} -
- ); +export const DocLink = ({docURL}) => { + if (!docURL) { + return null; } -}); - -export const ApiBarController = React.createClass({ - getWrap () { - return connectToStores(TrayWrapper, [componentStore], function () { - return { - buttonVisible: componentStore.getIsAPIBarButtonVisible(), - contentVisible: componentStore.getIsAPIBarVisible(), - endpoint: componentStore.getEndpoint(), - docURL: componentStore.getDocURL() - }; - }); - }, - - render () { - var TrayWrapper = this.getWrap(); - return ( - - - - ); - } -}); + return ( +
+ + + +
+ ); +}; diff --git a/app/addons/components/layouts.js b/app/addons/components/layouts.js index 72fd3d1fd..00454b47b 100644 --- a/app/addons/components/layouts.js +++ b/app/addons/components/layouts.js @@ -13,26 +13,18 @@ import React from 'react'; import ReactDOM from 'react-dom'; import {NotificationCenterButton} from '../fauxton/notifications/notifications'; -import {ApiBarController} from './components/apibar'; +import {JSONLink, DocLink} from './components/apibar'; import {Breadcrumbs} from './header-breadcrumbs'; -import ComponentActions from './actions'; export const ApiBarWrapper = ({docURL, endpoint}) => { - //TODO once all modules are using this remove actions and make them props - setTimeout(() => { - ComponentActions.updateAPIBar({ - buttonVisible: true, - contentVisible: false, - endpoint, - docURL - }); - }); return ( -
- + +
); }; @@ -96,13 +88,13 @@ export const OnePaneFooter = ({children}) => { ); }; -export const OnePaneSimpleLayout = ({component, docUrl, endpoint, crumbs}) => { +export const OnePaneSimpleLayout = ({component, docURL, endpoint, crumbs}) => { return ( @@ -122,13 +114,13 @@ export const DocEditorContent = ({children}) => { ); }; -export const DocEditorLayout = ({component, docUrl, endpoint, crumbs}) => { +export const DocEditorLayout = ({component, docURL, endpoint, crumbs}) => { return (
diff --git a/app/addons/components/stores.js b/app/addons/components/stores.js index af5a69c18..504c6bc51 100644 --- a/app/addons/components/stores.js +++ b/app/addons/components/stores.js @@ -15,76 +15,6 @@ import app from "../../app"; import ActionTypes from "./actiontypes"; var Stores = {}; -Stores.ComponentStore = FauxtonAPI.Store.extend({ - initialize: function () { - this.reset(); - }, - - reset: function () { - this._apiBarVisible = false; - this._apiBarButtonVisible = true; - this._endpoint = ''; - this._docURL = FauxtonAPI.constants.DOC_URLS.GENERAL; - }, - - updateAPIBar: function (settings) { - this._apiBarVisible = settings.contentVisible; - this._apiBarButtonVisible = settings.buttonVisible; - this._endpoint = settings.endpoint; - this._docURL = settings.docURL; - }, - - setVisibleButton: function (state) { - this._apiBarButtonVisible = state; - }, - - setApiBarVisible: function (state) { - this._apiBarVisible = state; - }, - - getEndpoint: function () { - return this._endpoint; - }, - - getDocURL: function () { - return this._docURL; - }, - - getIsAPIBarButtonVisible: function () { - return this._apiBarButtonVisible; - }, - - getIsAPIBarVisible: function () { - return this._apiBarVisible; - }, - - dispatch: function (action) { - switch (action.type) { - case ActionTypes.CMPNTS_SHOW_API_BAR_BUTTON: - this.setVisibleButton(true); - break; - - case ActionTypes.CMPNTS_HIDE_API_BAR_BUTTON: - this.setVisibleButton(false); - break; - - case ActionTypes.CMPNTS_SET_API_BAR_CONTENT_VISIBLE_STATE: - this.setApiBarVisible(action.options); - break; - - case ActionTypes.CMPNTS_UPDATE_API_BAR: - this.updateAPIBar(action.options); - break; - - default: - return; - // do nothing - } - - this.triggerChange(); - } -}); - Stores.DeleteDbModalStore = FauxtonAPI.Store.extend({ initialize: function () { this.reset(); @@ -123,7 +53,4 @@ Stores.DeleteDbModalStore = FauxtonAPI.Store.extend({ Stores.deleteDbModalStore = new Stores.DeleteDbModalStore(); Stores.deleteDbModalStore.dispatchToken = FauxtonAPI.dispatcher.register(Stores.deleteDbModalStore.dispatch); -Stores.componentStore = new Stores.ComponentStore(); -Stores.componentStore.dispatchToken = FauxtonAPI.dispatcher.register(Stores.componentStore.dispatch); - export default Stores; diff --git a/app/addons/components/tests/apiBarControllerSpec.js b/app/addons/components/tests/apiBarControllerSpec.js deleted file mode 100644 index 028f742a2..000000000 --- a/app/addons/components/tests/apiBarControllerSpec.js +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -import Actions from "../actions"; -import Stores from "../stores"; -import utils from "../../../../test/mocha/testUtils"; -import React from "react"; -import ReactDOM from "react-dom"; -import {ApiBarController} from '../components/apibar'; -import {mount} from 'enzyme'; - -const assert = utils.assert; -const componentStore = Stores.componentStore; - - -describe('ApiBarController', () => { - afterEach(() => { - componentStore.reset(); - }); - - it('Doesn\'t show up when explicitly set to visible false', () => { - const el = mount(); - Actions.updateAPIBar({ - buttonVisible: false, - endpoint: 'http://link.example.com', - docURL: 'http://link.example.com', - contentVisible: false - }); - assert.equal(el.find('.control-toggle-api-url').length, 0); - }); - - it('Shows up when set to visible', () => { - const el = mount(); - Actions.updateAPIBar({ - buttonVisible: true, - endpoint: 'http://link.example.com', - docURL: 'http://link.example.com', - contentVisible: false - }); - assert.equal(el.find('.control-toggle-api-url').length, 1); - }); - - it('Doesn\'t show up when set to visible BUT there\'s no endpoint defined', () => { - const el = mount(); - Actions.updateAPIBar({ - buttonVisible: true, - endpoint: '', - docURL: 'http://link.example.com', - contentVisible: false - }); - assert.equal(el.find('.control-toggle-api-url').length, 0); - }); - - it('Confirm hide/show actions update component', () => { - const el = mount(); - - Actions.updateAPIBar({ - buttonVisible: true, - endpoint: 'http://rocko.example.com', - docURL: 'http://link.example.com', - contentVisible: false - }); - - Actions.showAPIBarButton(); - assert.equal(el.find('.control-toggle-api-url').length, 1, 'showAPIBarButton'); - - Actions.hideAPIBarButton(); - assert.equal(el.find('.control-toggle-api-url').length, 0, 'hideAPIBarButton'); - }); - -}); diff --git a/app/addons/components/tests/nightwatch/copyToClipboard.js b/app/addons/components/tests/nightwatch/copyToClipboard.js deleted file mode 100644 index 2dcd81523..000000000 --- a/app/addons/components/tests/nightwatch/copyToClipboard.js +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - - -module.exports = { - - // Since we can't directly access the clipboard to verify, we'll confirm that - // the text to copy is correct and the successful callback is displayed. - - 'Copy API URL to Clipboard Test' : (client) => { - - const waitTime = client.globals.maxWaitTime; - const baseUrl = client.globals.test_settings.launch_url; - - client - .loginToGUI() - .url(baseUrl + '/#/_all_dbs') - - .clickWhenVisible('.control-toggle-api-url', waitTime, false) - .waitForElementVisible('.text-field-to-copy', waitTime, false) - .assert.attributeEquals('.text-field-to-copy', 'value', baseUrl + '/_all_dbs') - .waitForElementVisible('.copy-button', waitTime, false) - .assert.attributeEquals('.copy-button', 'data-clipboard-text', baseUrl + '/_all_dbs') - .click('.copy-button') - .waitForElementVisible('.global-notification', waitTime, false) - .assert.containsText('.global-notification > span', 'The API URL has been copied to the clipboard.') - .end(); - }, - - 'Copy MD5 Checksum to Clipboard Test' : (client) => { - - const waitTime = client.globals.maxWaitTime; - const newDatabaseName = client.globals.testDatabaseName; - const baseUrl = client.globals.test_settings.launch_url; - - client - .loginToGUI() - .populateDatabase(newDatabaseName) - .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs') - - .clickWhenVisible('.design-doc-name > span', waitTime, false) - .clickWhenVisible('a[href*="_info"]', waitTime, false) - .clickWhenVisible('li > button.clipboard-copy-element', waitTime, false) - .waitForElementVisible('.global-notification', waitTime, false) - .assert.containsText('.global-notification > span', 'The MD5 sha has been copied to your clipboard.') - .end(); - }, - - 'Copy Changes Feed Data to Clipboard Test' : (client) => { - - const waitTime = client.globals.maxWaitTime; - const newDatabaseName = client.globals.testDatabaseName; - const baseUrl = client.globals.test_settings.launch_url; - - client - .loginToGUI() - .url(baseUrl + '/#/database/' + newDatabaseName + '/_changes') - - .clickWhenVisible('.change-wrapper:first-child .row-fluid:first-child .clipboard-copy-element', waitTime, false) - .waitForElementVisible('.global-notification', waitTime, false) - .assert.containsText('.global-notification > span', 'The document seq number has been copied to your clipboard.') - .clickWhenVisible('.change-wrapper:first-child .row-fluid:nth-child(2) .clipboard-copy-element', waitTime, false) - .waitForElementVisible('.global-notification', waitTime, false) - .assert.containsText('.global-notification > span', 'The document ID has been copied to your clipboard.') - .end(); - }, - - 'Cppy Document from Table View to Clipboard Test' : (client) => { - const waitTime = client.globals.maxWaitTime; - const newDatabaseName = client.globals.testDatabaseName; - const baseUrl = client.globals.test_settings.launch_url; - - client - .loginToGUI() - .populateDatabase(newDatabaseName) - .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs') - - .waitForElementPresent('.doc-item', waitTime, false) - .clickWhenVisible('.fonticon-table', waitTime, false) - .clickWhenVisible('.table-view-docs tr:first-child .clipboard-copy-element', waitTime, false) - .waitForElementVisible('.global-notification', waitTime, false) - .assert.containsText('.global-notification > span', 'The document content has been copied to the clipboard.') - .end(); - } -}; diff --git a/app/addons/databases/layout.js b/app/addons/databases/layout.js index e83548e65..f2d3079f3 100644 --- a/app/addons/databases/layout.js +++ b/app/addons/databases/layout.js @@ -22,7 +22,7 @@ export const Layout = () => { diff --git a/app/addons/documents/tests/nightwatch/createsDocument.js b/app/addons/documents/tests/nightwatch/createsDocument.js index a04f21252..189456755 100644 --- a/app/addons/documents/tests/nightwatch/createsDocument.js +++ b/app/addons/documents/tests/nightwatch/createsDocument.js @@ -32,7 +32,7 @@ module.exports = { // confirm the header elements are showing up .waitForElementVisible('.faux-header__breadcrumbs', waitTime, true) - .waitForElementVisible('#api-navbar', waitTime, true) + .waitForElementVisible('.faux__jsonlink-link', waitTime, true) .execute('\ var editor = ace.edit("doc-editor");\ diff --git a/app/addons/documents/tests/nightwatch/createsDocumentWithoutId.js b/app/addons/documents/tests/nightwatch/createsDocumentWithoutId.js index 88ac793e8..464db4b67 100644 --- a/app/addons/documents/tests/nightwatch/createsDocumentWithoutId.js +++ b/app/addons/documents/tests/nightwatch/createsDocumentWithoutId.js @@ -32,7 +32,7 @@ module.exports = { // confirm the header elements are showing up .waitForElementVisible('.faux-header__breadcrumbs', waitTime, true) - .waitForElementVisible('#api-navbar', waitTime, true) + .waitForElementVisible('.faux__jsonlink-link', waitTime, true) .execute('\ var editor = ace.edit("doc-editor");\ diff --git a/app/addons/fauxton/tests/nightwatch/updatesUrlsSameRouteobject.js b/app/addons/fauxton/tests/nightwatch/updatesUrlsSameRouteobject.js index 4dfd216f2..39c3ca052 100644 --- a/app/addons/fauxton/tests/nightwatch/updatesUrlsSameRouteobject.js +++ b/app/addons/fauxton/tests/nightwatch/updatesUrlsSameRouteobject.js @@ -11,7 +11,6 @@ // the License. - module.exports = { 'it updates the API url even for routes in the same routeobject' : function (client) { var waitTime = client.globals.maxWaitTime, @@ -22,17 +21,12 @@ module.exports = { .populateDatabase(newDatabaseName) .loginToGUI() .url(baseUrl + '/#/database/' + newDatabaseName + '/_find') - .clickWhenVisible('.control-toggle-api-url') - .waitForElementVisible('.text-field-to-copy', waitTime, false) - .assert.valueContains('.text-field-to-copy', newDatabaseName + '/_find') + .waitForElementVisible('.faux__jsonlink-link', waitTime, false) + .assert.attributeContains('.faux__jsonlink-link', 'href', newDatabaseName + '/_find') .clickWhenVisible('.edit-link') .waitForElementVisible('.prettyprint', waitTime, false) - // We need to wait for the previous API Url modal to disappear before - // attempting to view it with the new text-field-to-copy. - .waitForElementNotPresent('.api-bar-tray', waitTime, false) - .clickWhenVisible('.control-toggle-api-url') - .waitForElementVisible('.text-field-to-copy', waitTime, false) - .assert.valueContains('.text-field-to-copy', newDatabaseName + '/_index') + .waitForElementVisible('.faux__jsonlink-link', waitTime, false) + .assert.attributeContains('.faux__jsonlink-link', 'href', newDatabaseName + '/_index') .end(); } }; diff --git a/package.json b/package.json index 924363ac6..01b5e255a 100644 --- a/package.json +++ b/package.json @@ -102,8 +102,8 @@ "underscore": "~1.4.2", "url": "~0.7.9", "url-loader": "^0.5.7", - "urls": "~0.0.3", "url-polyfill": "git+https://github.com/webcomponents/URL.git", + "urls": "~0.0.3", "uuid": "^3.0.1", "velocity-animate": "^1.4.2", "velocity-react": "1.2.0",