You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by db...@apache.org on 2016/02/24 19:18:03 UTC
[05/10] ambari git commit: AMBARI-15145. Revamped Filebrowser Design
- UI. (dipayanb)
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/context-row-menu.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/context-row-menu.js b/contrib/views/files/src/main/resources/ui/app/components/context-row-menu.js
new file mode 100644
index 0000000..1e9551b
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/context-row-menu.js
@@ -0,0 +1,137 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+
+export default Ember.Component.extend({
+ fileSelectionService: Ember.inject.service('files-selection'),
+ modalEventBus: Ember.inject.service('modal-event-bus'),
+ alertMessages: Ember.inject.service('alert-messages'),
+ filesDownloadService: Ember.inject.service('files-download'),
+
+ classNames: ['row', 'context-menu-row'],
+ selectedFilesCount: Ember.computed.oneWay('fileSelectionService.filesCount'),
+ selectedFolderCount: Ember.computed.oneWay('fileSelectionService.folderCount'),
+ isMultiSelected: Ember.computed('selectedFilesCount', 'selectedFolderCount', function() {
+ return this.get('selectedFilesCount') + this.get('selectedFolderCount') > 1;
+ }),
+ isSingleSelected: Ember.computed('selectedFilesCount', 'selectedFolderCount', function() {
+ return this.get('selectedFilesCount') + this.get('selectedFolderCount') === 1;
+ }),
+ isSelected: Ember.computed('selectedFilesCount', 'selectedFolderCount', function() {
+ return (this.get('selectedFilesCount') + this.get('selectedFolderCount')) !== 0;
+ }),
+ isOnlyMultiFilesSelected: Ember.computed('selectedFilesCount', 'selectedFolderCount', function() {
+ return this.get('selectedFolderCount') === 0 && this.get('selectedFilesCount') > 1;
+ }),
+
+ didInitAttrs: function() {
+ // Register different modal so that they can be controlled from outside
+ this.get('modalEventBus').registerModal('ctx-open');
+ this.get('modalEventBus').registerModal('ctx-rename');
+ this.get('modalEventBus').registerModal('ctx-permission');
+ this.get('modalEventBus').registerModal('ctx-delete');
+ this.get('modalEventBus').registerModal('ctx-copy');
+ this.get('modalEventBus').registerModal('ctx-move');
+ this.get('modalEventBus').registerModal('ctx-download');
+ this.get('modalEventBus').registerModal('ctx-concatenate');
+ },
+
+ willDestroyElement() {
+ this.get('modalEventBus').resetModal('ctx-open');
+ this.get('modalEventBus').resetModal('ctx-rename');
+ this.get('modalEventBus').resetModal('ctx-permission');
+ this.get('modalEventBus').resetModal('ctx-delete');
+ this.get('modalEventBus').resetModal('ctx-copy');
+ this.get('modalEventBus').resetModal('ctx-move');
+ this.get('modalEventBus').resetModal('ctx-download');
+ this.get('modalEventBus').resetModal('ctx-concatenate');
+ },
+
+ actions: {
+ open: function(event) {
+ if (this.get('isSingleSelected')) {
+ var file = this.get('fileSelectionService.files').objectAt(0);
+ if (file.get('isDirectory')) {
+ this.sendAction('openFolderAction', file.get('path'));
+ } else {
+ this.get('modalEventBus').showModal('ctx-open');
+ }
+ }
+
+ },
+
+ delete: function(event) {
+ if (!this.get('isSelected')) {
+ return false;
+ }
+ this.get('modalEventBus').showModal('ctx-delete');
+ },
+
+ copy: function(event) {
+ if (!this.get('isSelected')) {
+ return false;
+ }
+ this.get('modalEventBus').showModal('ctx-copy');
+ },
+
+ move: function(event) {
+ if (!this.get('isSelected')) {
+ return false;
+ }
+ this.get('modalEventBus').showModal('ctx-move');
+ },
+
+ download: function(event) {
+ if (!this.get('isSelected')) {
+ return false;
+ }
+ this.get('filesDownloadService').download();
+ },
+
+ concatenate: function(event) {
+ if (!this.get('isOnlyMultiFilesSelected')) {
+ return false;
+ }
+ this.get('filesDownloadService').concatenate();
+ },
+
+ rename: function(event) {
+ if (!this.get('isSingleSelected')) {
+ return false;
+ }
+ this.get('modalEventBus').showModal('ctx-rename');
+ },
+ permission: function(event) {
+ if (!this.get('isSingleSelected')) {
+ return false;
+ }
+ this.get('modalEventBus').showModal('ctx-permission');
+ },
+
+ modalClosed: function(modalName) {
+ this.get('modalEventBus').resetModal(modalName);
+ },
+
+ refreshCurrentRoute: function() {
+ this.get('fileSelectionService').reset();
+ this.sendAction('refreshCurrentRouteAction');
+ }
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/contextMenu.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/contextMenu.js b/contrib/views/files/src/main/resources/ui/app/components/contextMenu.js
deleted file mode 100644
index 0c715dc..0000000
--- a/contrib/views/files/src/main/resources/ui/app/components/contextMenu.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-var App = require('app');
-
-App.ContextMenuComponent = Em.Component.extend({
- layoutName:'components/contextMenu',
-
- onTargetChange:function () {
- this.$().off('hidden.bs.context');
- this.$().on('hidden.bs.context', Em.run.bind(this, this.resetConfirmations));
- }.observes('target'),
-
- resetConfirmations:function () {
- this.triggerRecursively('resetConfirm');
- },
-
- actions:{
- removeFile:function () {
- this.get('target').send('deleteFile',true);
- },
- moveToTrash:function () {
- this.get('target').send('deleteFile');
- }
- }
-
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/copy-modal.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/copy-modal.js b/contrib/views/files/src/main/resources/ui/app/components/copy-modal.js
new file mode 100644
index 0000000..79a78ec
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/copy-modal.js
@@ -0,0 +1,126 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+
+export default Ember.Component.extend(OperationModal, {
+ closeOnEscape: true,
+ fileSelectionService: Ember.inject.service('files-selection'),
+ fileOperationService: Ember.inject.service('file-operation'),
+ selectedFiles: Ember.computed.alias('fileSelectionService.files'),
+ selected: Ember.computed('selectedFiles', function () {
+ return this.get('selectedFiles').objectAt(0);
+ }),
+ selectionName: '/',
+ isUpdating: false,
+ browseError: false,
+ browseErrorMessege: '',
+ hasError: false,
+ shouldRetry: false,
+ currentFailedPath: '',
+ currentUnprocessedPaths: [],
+ currentFailureMessage: '',
+
+ copyPaths: function (paths, destination) {
+ this.set('isUpdating', true);
+
+ this.get('fileOperationService').copyPaths(paths, destination).then(
+ (response) => {
+ this.set('isUpdating', false);
+ this.send('close');
+ this.sendAction('refreshAction');
+ }, (error) => {
+ this.set('isUpdating', false);
+ if (error.unprocessable === true) {
+ this.set('hasError', true);
+ this.set('currentFailedPath', error.failed);
+ this.set('currentFailureMessage', error.message);
+ this.set('shouldRetry', error.retry);
+ this.set('currentUnprocessedPaths', error.unprocessed);
+ } else {
+ this.set('isUpdating', false);
+ this.get('logger').danger("Failed to delete files and folders.", error);
+ this.send('close');
+ }
+ });
+ },
+ reset: function () {
+ this.set('browseError', false);
+ this.set('browseErrorMessege', '');
+ this.set('selectionName', '/');
+ this.set('hasError', false);
+ this.set('shouldRetry', false);
+ this.set('isUpdating', false);
+ this.set('currentFailedPath', '');
+ this.set('currentFailureMessage', '');
+ this.set('currentUnprocessedPaths', '');
+ },
+ actions: {
+
+ didOpenModal: function () {
+ this.reset();
+ console.log("Move modal opened");
+ },
+
+ didCloseModal: function () {
+ console.log("Move Modal did close.");
+ },
+
+ copy: function () {
+ var currentPathsToMove = this.get('selectedFiles').map((entry) => {
+ return entry.get('path')
+ });
+ var destinationPath = (this.get('selectionName') !== '') ? this.get('selectionName') : '/';
+ this.copyPaths(currentPathsToMove, destinationPath);
+ },
+
+ retryError: function () {
+ var newPaths = [this.get('currentFailedPath')];
+ if (Ember.isArray(this.get('currentUnprocessedPaths'))) {
+ newPaths.pushObjects(this.get('currentUnprocessedPaths'));
+ }
+ var destinationPath = (this.get('selectionName') !== '') ? this.get('selectionName') : '/';
+ this.copyPaths(newPaths, destinationPath);
+ },
+
+ skipAndRetry: function () {
+ var destinationPath = (this.get('selectionName') !== '') ? this.get('selectionName') : '/';
+ this.copyPaths(this.get('currentUnprocessedPaths'), destinationPath);
+ },
+
+ skipAll: function () {
+ this.send('close');
+ this.sendAction('refreshAction');
+ },
+
+ pathSelected: function (path) {
+ console.log(path);
+ this.set('selectionName', path);
+ this.set('browseError', false);
+
+ },
+
+ browseError: function (error) {
+ this.set('browseError', true);
+ this.set('browseErrorMessage', error.message);
+ }
+ }
+
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/delete-modal.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/delete-modal.js b/contrib/views/files/src/main/resources/ui/app/components/delete-modal.js
new file mode 100644
index 0000000..cb71ba7
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/delete-modal.js
@@ -0,0 +1,130 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+
+export default Ember.Component.extend(OperationModal, {
+ fileSelectionService: Ember.inject.service('files-selection'),
+ fileOperationService: Ember.inject.service('file-operation'),
+ logger: Ember.inject.service('alert-messages'),
+ closeOnEscape: true,
+ deletePermanently: false,
+ deletePermanentlyAlways: false,
+ showDeletePermanentCheckbox: true,
+ selectedFiles: Ember.computed.alias('fileSelectionService.files'),
+ filesCount: Ember.computed.oneWay('fileSelectionService.filesCount'),
+ folderCount: Ember.computed.oneWay('fileSelectionService.folderCount'),
+ hasFiles: Ember.computed('filesCount', function() {
+ return this.get('filesCount') > 0;
+ }),
+ hasFolders: Ember.computed('folderCount', function() {
+ return this.get('folderCount') > 0;
+ }),
+ hasError: false,
+ shouldRetry: false,
+ currentFailedPath: '',
+ currentUnprocessedPaths: [],
+ currentFailureMessage: '',
+ currentServerFailureMessage: '',
+ isDeleting: false,
+
+ setTrashSettings: Ember.on('init', Ember.observer('currentPathIsTrash', function() {
+ if(this.get('currentPathIsTrash')) {
+ this.set('deletePermanentlyAlways', true);
+ this.set('showDeletePermanentCheckbox', false);
+ } else {
+ this.set('deletePermanentlyAlways', false);
+ this.set('showDeletePermanentCheckbox', true);
+ }
+
+ })),
+
+ disableCloseOnEscape: Ember.observer('isDeleting', function() {
+ if (this.get('isDeleting') === true) {
+ this.set('closeOnEscape', false);
+ } else {
+ this.set('closeOnEscape', true);
+ }
+ }),
+
+ deletePaths: function(paths) {
+ this.set('isDeleting', true);
+ let deletePermanently = this.get('deletePermanently');
+ if(this.get('deletePermanentlyAlways')) {
+ deletePermanently = true;
+ }
+ this.get('fileOperationService').deletePaths(paths, deletePermanently).then(
+ (response) => {
+ this.set('isDeleting', false);
+ this.send('close');
+ this.sendAction('refreshAction');
+ }, (error) => {
+ this.set('isDeleting', false);
+ if (error.unprocessable === true) {
+ this.set('hasError', true);
+ this.set('currentFailedPath', error.failed);
+ this.set('currentServerFailureMessage', error.message);
+ this.set('currentFailureMessage', `Failed to delete <strong>${error.failed}</strong>.`);
+ this.set('shouldRetry', error.retry);
+ this.set('currentUnprocessedPaths', error.unprocessed);
+ } else {
+ this.set('isDeleting', false);
+ this.get('logger').danger("Failed to delete files and folders.", error);
+ this.send('close');
+ }
+ });
+ },
+ reset: function() {
+ this.set('deletePermanently', false);
+ this.set('hasError', false);
+ this.set('shouldRetry', false);
+ this.set('isDeleting', false);
+ this.set('currentFailedPath', '');
+ this.set('currentFailureMessage', '');
+ this.set('currentUnprocessedPaths', '');
+ },
+ actions: {
+ didOpenModal: function() {
+ this.reset();
+ console.log("Delete modal opened");
+ },
+
+ didCloseModal: function() {
+ console.log("Delete Modal closed");
+ },
+ delete: function() {
+ var currentPathsToDelete = this.get('selectedFiles').map((entry) => { return entry.get('path');});
+ this.deletePaths(currentPathsToDelete);
+ },
+ retryError: function() {
+ var newPaths = [this.get('currentFailedPath')];
+ if (Ember.isArray(this.get('currentUnprocessedPaths'))) {
+ newPaths.pushObjects(this.get('currentUnprocessedPaths'));
+ }
+ this.deletePaths(newPaths);
+ },
+ skipAndRetry: function() {
+ this.deletePaths(this.get('currentUnprocessedPaths'));
+ },
+ skipAll: function() {
+ this.send('close');
+ this.sendAction('refreshAction');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/directory-viewer.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/directory-viewer.js b/contrib/views/files/src/main/resources/ui/app/components/directory-viewer.js
new file mode 100644
index 0000000..69e725b
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/directory-viewer.js
@@ -0,0 +1,165 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import FileOperationMixin from '../mixins/file-operation';
+
+export default Ember.Component.extend(FileOperationMixin, {
+ fileOperationService: Ember.inject.service('file-operation'),
+ classNames: ['directory-viewer'],
+ startPath: '/',
+ treeData: Ember.A(),
+ currentPath: Ember.computed.oneWay('startPath'),
+ currentQueryParam: Ember.computed('currentPath', function() {
+ return Ember.$.param({path: this.get('currentPath')});
+ }),
+
+ startFetch: Ember.on('didInitAttrs', function() {
+ this.fetchData();
+ }),
+
+ fetchData: function() {
+ this.get('fileOperationService').listPath(this.get('currentQueryParam')).then(
+ (response) => {
+ this.modifyTreeViewData(response);
+ }, (error) => {
+ this.sendAction('errorAction', error);
+ }
+ )
+ },
+
+ modifyTreeViewData: function(response) {
+
+ let paths = response.map((entry) => {
+ return {
+ path: entry.path,
+ pathSegment: this.getNameForPath(entry.path),
+ text: this.getNameForPath(entry.path),
+ nodes: Ember.A()
+ };
+ });
+
+ var currentPath = this.get('currentPath');
+ var newTreeData = Ember.copy(this.get('treeData'), true);
+ if(currentPath === '/') {
+ newTreeData = paths;
+ } else {
+ this.insertPathToTreeData(newTreeData, paths, currentPath.substring(1));
+ }
+
+ this.set('treeData', newTreeData);
+ this.send('refreshTreeView');
+ },
+
+ insertPathToTreeData(treeData, paths, pathSegment) {
+ let firstPathSegment;
+ if (pathSegment.indexOf('/') !== -1) {
+ firstPathSegment = pathSegment.substring(0, pathSegment.indexOf('/'));
+ } else {
+ firstPathSegment = pathSegment;
+ }
+
+ if(treeData.length === 0) {
+ treeData.pushObjects(paths);
+ } else {
+ treeData.forEach((entry) => {
+ entry.state = {};
+ if (entry.pathSegment === firstPathSegment) {
+ entry.state.expanded = true;
+ if(entry.nodes.length === 0) {
+ entry.nodes.pushObjects(paths);
+ } else {
+ this.insertPathToTreeData(entry.nodes, paths, pathSegment.substring(pathSegment.indexOf('/') + 1));
+ }
+ } else {
+ this.collapseAll(entry);
+ }
+ });
+ }
+ },
+
+ collapseAll: function(node) {
+ if (Ember.isNone(node.state)) {
+ node.state = {};
+ }
+ node.state.expanded = false;
+ node.nodes.forEach((entry) => {
+ this.collapseAll(entry);
+ });
+
+ },
+
+ getNameForPath: function(path) {
+ return path.substring(path.lastIndexOf("/") + 1);
+ },
+
+ collapseAllExceptPath: function(pathSegment) {
+ let collapseAll = function(nodes, pathSegment) {
+ var firstPathSegment;
+ if (pathSegment.indexOf('/') !== -1) {
+ firstPathSegment = pathSegment.substring(0, pathSegment.indexOf('/'));
+ } else {
+ firstPathSegment = pathSegment;
+ }
+
+ nodes.forEach((entry) => {
+ if (Ember.isNone(entry.state)) {
+ entry.state = {};
+ }
+ if(firstPathSegment !== entry.pathSegment) {
+ entry.state.expanded = false;
+ } else {
+ entry.state.expanded = true;
+ collapseAll(entry.nodes, pathSegment.substring(pathSegment.indexOf('/') + 1));
+ }
+ });
+ };
+ var newTreeData = this.get('treeData');
+ collapseAll(newTreeData, pathSegment);
+ this.set('treeData', newTreeData);
+ this.send('refreshTreeView');
+ },
+
+ actions: {
+ refreshTreeView() {
+ Ember.run.later(() => {
+ this.$().treeview({
+ data: this.get('treeData'),
+ expandIcon: "fa fa-folder",
+ collapseIcon: "fa fa-folder-open",
+ emptyIcon: "fa fa-folder-open-o",
+ showBorder: false,
+ onNodeSelected: (event, data) => {
+ this.set('currentPath', data.path);
+ this.sendAction('pathSelectAction', data.path);
+ },
+ onNodeExpanded: (event, data) => {
+ this.set('currentPath', data.path);
+ if (!Ember.isNone(data.nodes) && data.nodes.length === 0) {
+ var node = this.$().treeview('getNode', data.nodeId);
+ node.icon = "fa fa-refresh fa-spin";
+ this.fetchData();
+ } else {
+ this.collapseAllExceptPath(data.path.substring(1));
+ }
+ }
+ });
+ });
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/file-row.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/file-row.js b/contrib/views/files/src/main/resources/ui/app/components/file-row.js
new file mode 100644
index 0000000..a7fdbee
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/file-row.js
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['col-md-12', 'file-row'],
+ classNameBindings: ['isSelected:row-selected'],
+ isSelected: Ember.computed.alias('file.isSelected'),
+
+ click: function(event) {
+ if(event.shiftKey) {
+ this.sendAction("multiSelectAction", this.get('file'), true);
+ } else if (event.ctrlKey) {
+ this.sendAction("multiSelectAction", this.get('file'), false);
+ } else if (event.metaKey) {
+ this.sendAction("multiSelectAction", this.get('file'), false);
+ } else {
+ this.sendAction("singleSelectAction", this.get('file'));
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/file-search.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/file-search.js b/contrib/views/files/src/main/resources/ui/app/components/file-search.js
new file mode 100644
index 0000000..b65749c
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/file-search.js
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['input-group'],
+ classNameBindings: ['expanded::col-md-9', 'expanded::col-md-offset-3'],
+ expanded: false,
+
+ searchText: '',
+
+ throttleTyping: Ember.observer('searchText', function() {
+ Ember.run.debounce(this, this.searchFiles, 500);
+ }),
+
+ searchFiles: function() {
+ this.sendAction('searchAction', this.get('searchText'));
+ },
+
+ focusIn: function() {
+ this.set('expanded', true);
+ },
+ focusOut: function() {
+ this.set('expanded', false);
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/files-breadcrumb.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/files-breadcrumb.js b/contrib/views/files/src/main/resources/ui/app/components/files-breadcrumb.js
new file mode 100644
index 0000000..be3054c
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/files-breadcrumb.js
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+
+export default Ember.Component.extend({
+ path: '',
+ collapseAt: 4,
+ tagName: 'ul',
+ classNames: ['breadcrumb'],
+ collapsingRequired: false,
+ collapsedCrumbs: [],
+ expandedCrumbs: [],
+
+ crumbs: Ember.on('init', Ember.observer('path', function() {
+ var path = this.get('path');
+ var currentPath = path.split('/').filter((entry) => { return !Ember.isBlank(entry) });
+ currentPath.unshift("/");
+ var that = this;
+ var shouldCollapse = function(scope, array, index) {
+ return (((array.length - 1) >= scope.get('collapseAt')) && (index < array.length - 2));
+ };
+ var getCrumb = function(index, allCrumbs) {
+ return {name: allCrumbs[index], path: "/" + allCrumbs.slice(1, index + 1).join('/'), last: false};
+ };
+
+ var collapsedCrumbs = currentPath.map(function(curr, i, array) {
+ if(shouldCollapse(that, array, i)) {
+ return getCrumb(i, array);
+ } else {
+ return {};
+ }
+ }).filterBy('name');
+
+ var crumbs = currentPath.map(function(curr, i, array) {
+ if(!shouldCollapse(that, array, i)) {
+ return getCrumb(i, array);
+ } else {
+ return {};
+ }
+ }).filterBy('name');
+
+ crumbs.set('lastObject.last', true);
+
+ if (collapsedCrumbs.length > 0) {
+ this.set('collapsingRequired', true);
+ } else {
+ this.set('collapsingRequired', false);
+ }
+ this.set('collapsedCrumbs', collapsedCrumbs.reverse());
+ this.set('expandedCrumbs', crumbs);
+ }))
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/files-collection.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/files-collection.js b/contrib/views/files/src/main/resources/ui/app/components/files-collection.js
new file mode 100644
index 0000000..43ef243
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/files-collection.js
@@ -0,0 +1,98 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import { EKMixin, keyUp } from 'ember-keyboard';
+
+export default Ember.Component.extend(EKMixin, {
+ minHeight: 600,
+ currentWidth: 1000,
+ currentHeight: 600,
+ columnsConfig: [],
+ sortOptions: [-1, 0, 1],
+ parentPath: '',
+ isEmptyParentPath: Ember.computed('parentPath', function() {
+ return Ember.isBlank(this.get('parentPath'));
+ }),
+
+ resizeView: Ember.on('init', function() {
+ $(window).resize(this.windowResized(this));
+ }),
+
+ destroyResizeView: Ember.on('willDestroyElement', function() {
+ $(window).off("resize");
+ }),
+
+ activateKeyboard: Ember.on('init', function() {
+ this.set('keyboardActivated', true);
+ }),
+
+ resetAllSelection: Ember.on(keyUp('Escape'), function() {
+ this.sendAction('resetSelection');
+ }),
+
+ selectAll: Ember.on(keyUp('shift+s'), function() {
+ this.sendAction('selectAllAction', false);
+ }),
+
+ containerStyle: Ember.computed('currentHeight', function() {
+ var height = this.get('currentHeight');
+ var style = 'position: relative; height: ' + height + 'px';
+ return style.htmlSafe();
+ }),
+
+ windowResized: function(scope) {
+ return function() {
+ Ember.run.later(function() {
+ var currentWidth = $("#" + scope.get('containerId')).width();
+ var windowHeight = $(window).height();
+ var relativeHeight = windowHeight - 220;
+ if(relativeHeight < scope.get('minHeight')) {
+ relativeHeight = scope.get('minHeight');
+ }
+ scope.set('currentWidth', currentWidth);
+ scope.set('currentHeight', relativeHeight);
+ });
+ };
+ },
+
+ didInsertElement: function() {
+ var func = this.windowResized(this);
+ func();
+ },
+
+ actions: {
+ rotateSort: function(column) {
+ if(!column['sortable'] || this.get('sortEnabled') !== true) {
+ return false;
+ }
+ var sortOptions = this.get('sortOptions');
+ // Resetting the current sort order
+ this.get('columnsConfig').forEach(function(entry) {
+ if(entry['key'] !== column['key']) {
+ Ember.set(entry, 'sortOrder', sortOptions[1]);
+ }
+ });
+ var currentSortOrder = column['sortOrder'];
+ var currentSortOrderIndex = sortOptions.indexOf(currentSortOrder);
+ var nextSortOrderIndex = (currentSortOrderIndex + 1) % sortOptions.length;
+ Ember.set(column, 'sortOrder', sortOptions[nextSortOrderIndex]);
+ this.sendAction('sortAction', column);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/mkdirInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/mkdirInput.js b/contrib/views/files/src/main/resources/ui/app/components/mkdirInput.js
deleted file mode 100644
index d98a429..0000000
--- a/contrib/views/files/src/main/resources/ui/app/components/mkdirInput.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-var App = require('app');
-
-App.MkdirInputComponent = Em.Component.extend({
- layoutName:'components/mkdirInput',
- newDirName:'',
- isMkdir:false,
- path:'',
- actions:{
- create:function () {
- var name = this.get('newDirName');
-
- if (Em.isEmpty(name)) {
- return false;
- }
- newDir = [this.get('path'),name].join('/').replace('//','/');
-
- this.sendAction('create',newDir);
- this.setProperties({'newDirName':'','isMkdir':false});
- },
- edit:function () {
- this.set('isMkdir',true);
- },
- cancel:function () {
- this.setProperties({'newDirName':'','isMkdir':false});
- }
- },
- focusOnInput: function () {
- Em.run.next(this,function() {
- this.$('.mkdir-input').focus();
- });
- }.observes('isMkdir'),
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/move-modal.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/move-modal.js b/contrib/views/files/src/main/resources/ui/app/components/move-modal.js
new file mode 100644
index 0000000..41de5f3
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/move-modal.js
@@ -0,0 +1,126 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+
+export default Ember.Component.extend(OperationModal, {
+ closeOnEscape: true,
+ fileSelectionService: Ember.inject.service('files-selection'),
+ fileOperationService: Ember.inject.service('file-operation'),
+ selectedFiles: Ember.computed.alias('fileSelectionService.files'),
+ selected: Ember.computed('selectedFiles', function () {
+ return this.get('selectedFiles').objectAt(0);
+ }),
+ selectionName: '/',
+ isUpdating: false,
+ browseError: false,
+ browseErrorMessege: '',
+ hasError: false,
+ shouldRetry: false,
+ currentFailedPath: '',
+ currentUnprocessedPaths: [],
+ currentFailureMessage: '',
+
+ movePaths: function (paths, destination) {
+ this.set('isUpdating', true);
+
+ this.get('fileOperationService').movePaths(paths, destination).then(
+ (response) => {
+ this.set('isUpdating', false);
+ this.send('close');
+ this.sendAction('refreshAction');
+ }, (error) => {
+ this.set('isUpdating', false);
+ if (error.unprocessable === true) {
+ this.set('hasError', true);
+ this.set('currentFailedPath', error.failed);
+ this.set('currentFailureMessage', error.message);
+ this.set('shouldRetry', error.retry);
+ this.set('currentUnprocessedPaths', error.unprocessed);
+ } else {
+ this.set('isUpdating', false);
+ this.get('logger').danger("Failed to delete files and folders.", error);
+ this.send('close');
+ }
+ });
+ },
+ reset: function () {
+ this.set('browseError', false);
+ this.set('browseErrorMessege', '');
+ this.set('selectionName', '/');
+ this.set('hasError', false);
+ this.set('shouldRetry', false);
+ this.set('isUpdating', false);
+ this.set('currentFailedPath', '');
+ this.set('currentFailureMessage', '');
+ this.set('currentUnprocessedPaths', '');
+ },
+ actions: {
+
+ didOpenModal: function () {
+ this.reset();
+ console.log("Move modal opened");
+ },
+
+ didCloseModal: function () {
+ console.log("Move Modal did close.");
+ },
+
+ move: function () {
+ var currentPathsToMove = this.get('selectedFiles').map((entry) => {
+ return entry.get('path')
+ });
+ var destinationPath = (this.get('selectionName') !== '') ? this.get('selectionName') : '/';
+ this.movePaths(currentPathsToMove, destinationPath);
+ },
+
+ retryError: function () {
+ var newPaths = [this.get('currentFailedPath')];
+ if (Ember.isArray(this.get('currentUnprocessedPaths'))) {
+ newPaths.pushObjects(this.get('currentUnprocessedPaths'));
+ }
+ var destinationPath = (this.get('selectionName') !== '') ? this.get('selectionName') : '/';
+ this.movePaths(newPaths, destinationPath);
+ },
+
+ skipAndRetry: function () {
+ var destinationPath = (this.get('selectionName') !== '') ? this.get('selectionName') : '/';
+ this.movePaths(this.get('currentUnprocessedPaths'), destinationPath);
+ },
+
+ skipAll: function () {
+ this.send('close');
+ this.sendAction('refreshAction');
+ },
+
+ pathSelected: function (path) {
+ console.log(path);
+ this.set('selectionName', path);
+ this.set('browseError', false);
+
+ },
+
+ browseError: function (error) {
+ this.set('browseError', true);
+ this.set('browseErrorMessage', error.message);
+ }
+ }
+
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/new-directory.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/new-directory.js b/contrib/views/files/src/main/resources/ui/app/components/new-directory.js
new file mode 100644
index 0000000..c30cc8c
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/new-directory.js
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+
+export default Ember.Component.extend(OperationModal, {
+ modalEventBus: Ember.inject.service('modal-event-bus'),
+ fileOperationService: Ember.inject.service('file-operation'),
+ closeOnEscape: true,
+ tagName: 'span',
+ name: 'ctx-new-directory',
+ hasError: false,
+ errorMessage: '',
+ folderName: '',
+ didInitAttrs: function() {
+ this.get('modalEventBus').registerModal("ctx-new-directory");
+ },
+ willDestroyElement() {
+ this.get('modalEventBus').resetModal("ctx-new-directory");
+ },
+ resetError: Ember.observer('folderName', function() {
+ this.set('hasError', false);
+ this.set('errorMessage', '');
+ }),
+ setError: function(message) {
+ this.set('hasError', true);
+ this.set('errorMessage', message);
+ },
+ actions: {
+ didOpenModal: function() {
+ this.set('folderName');
+ Ember.run.later(() => {
+ this.$('input').focus();
+ }, 500);
+ },
+ create: function() {
+ if(Ember.isBlank(this.get('folderName'))) {
+ this.setError('Cannot be empty');
+ return false;
+ }
+
+ if(this.get('fileOperationService').isExistsInCurrentPath(this.get('folderName'))) {
+ this.setError('Name already exists');
+ return false;
+ }
+
+ this.get('fileOperationService').createNewFolder(this.get('path'), this.get('folderName')).then(
+ (response) => {
+ this.send('close');
+ this.sendAction('refreshAction');
+ }, (error) => {
+ this.send('close');
+ });
+ },
+ openModal : function() {
+ this.get('modalEventBus').showModal('ctx-new-directory');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/open-preview-modal.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/open-preview-modal.js b/contrib/views/files/src/main/resources/ui/app/components/open-preview-modal.js
new file mode 100644
index 0000000..bc60227
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/open-preview-modal.js
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+
+export default Ember.Component.extend(OperationModal, {
+ closeOnEscape: true,
+ filePreviewService: Ember.inject.service('file-preview'),
+ selectedFilePath: '',
+ modalGuardChanged: Ember.observer('modalGuard', function () {
+ if (this.get('modalGuard')) {
+ console.log("Modal Guard set");
+ } else {
+ console.log("Modal Guard not set");
+ }
+ }),
+
+ actions: {
+ // Actions to preview modal HTML.
+ didOpenModal: function () {
+ this.set('selectedFilePath', this.get('filePreviewService.selectedFilePath'));
+ this.get('filePreviewService').getNextContent();
+ var _self = this;
+ this.$('.preview-content').on('scroll', function () {
+ if (Ember.$(this).scrollTop() + Ember.$(this).innerHeight() >= this.scrollHeight) {
+ _self.get('filePreviewService').getNextContent();
+ }
+ });
+ },
+ didCloseModal: function () {
+ this.$('.preview-content').off('scroll');
+ this.get('filePreviewService').reset();
+ },
+ download: function () {
+ this.get('filePreviewService').download();
+ }
+ }
+
+});
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/permission-modal.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/permission-modal.js b/contrib/views/files/src/main/resources/ui/app/components/permission-modal.js
new file mode 100644
index 0000000..706e839
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/permission-modal.js
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+
+export default Ember.Component.extend(OperationModal, {
+ fileSelectionService: Ember.inject.service('files-selection'),
+ fileOperationService: Ember.inject.service('file-operation'),
+ closeOnEscape: true,
+ isUpdating: false,
+ selected: Ember.computed('fileSelectionService.files', function() {
+ return this.get('fileSelectionService.files').objectAt(0);
+ }),
+ permission: Ember.computed('selected.permission', function() {
+ return this.get('selected.permission');
+ }),
+ setPermissionGuards: function() {
+ var permission = this.get('permission');
+ this.set('usrR', this.isSet(permission, 'user', "read"));
+ this.set('usrW', this.isSet(permission, 'user', "write"));
+ this.set('usrE', this.isSet(permission, 'user', "execute"));
+
+ this.set('grpR', this.isSet(permission, 'group', "read"));
+ this.set('grpW', this.isSet(permission, 'group', "write"));
+ this.set('grpE', this.isSet(permission, 'group', "execute"));
+
+ this.set('othR', this.isSet(permission, 'other', "read"));
+ this.set('othW', this.isSet(permission, 'other', "write"));
+ this.set('othE', this.isSet(permission, 'other', "execute"));
+ },
+
+ isSet: function(permission, userType, permissionType) {
+ var checkValueAtLocation = function(index, value) {
+ return permission[index] === value;
+ };
+
+ var checkValueForPermissionType = function(startIndex, permissionType) {
+ switch(permissionType) {
+ case 'read':
+ return checkValueAtLocation(startIndex, 'r');
+ case 'write':
+ return checkValueAtLocation(startIndex + 1, 'w');
+ case 'execute':
+ return checkValueAtLocation(startIndex + 2, 'x');
+ }
+ };
+ switch(userType) {
+ case "user":
+ return checkValueForPermissionType(1, permissionType);
+ case "group":
+ return checkValueForPermissionType(4, permissionType);
+ case "other":
+ return checkValueForPermissionType(7, permissionType);
+ }
+ },
+
+ getPermissionFromGuards: function() {
+ var oldPermission = this.get('permission');
+ var replaceAt = function(index, value) {
+ return oldPermission.substring(0, index) + value + oldPermission.substring(index + value.length);
+ };
+ oldPermission = this.get('usrR') ? replaceAt(1, 'r') : replaceAt(1, '-');
+ oldPermission = this.get('usrW') ? replaceAt(2, 'w') : replaceAt(2, '-');
+ oldPermission = this.get('usrE') ? replaceAt(3, 'x') : replaceAt(3, '-');
+ oldPermission = this.get('grpR') ? replaceAt(4, 'r') : replaceAt(4, '-');
+ oldPermission = this.get('grpW') ? replaceAt(5, 'w') : replaceAt(5, '-');
+ oldPermission = this.get('grpE') ? replaceAt(6, 'x') : replaceAt(6, '-');
+ oldPermission = this.get('othR') ? replaceAt(7, 'r') : replaceAt(7, '-');
+ oldPermission = this.get('othW') ? replaceAt(8, 'w') : replaceAt(8, '-');
+ oldPermission = this.get('othE') ? replaceAt(9, 'x') : replaceAt(9, '-');
+ return oldPermission;
+ },
+ actions: {
+ didOpenModal: function() {
+ this.setPermissionGuards();
+ },
+
+ chmod: function() {
+ var newPermission = this.getPermissionFromGuards();
+ if(newPermission === this.get('permission')) {
+ return false;
+ }
+ this.set('isUpdating', true);
+ this.get('fileOperationService').chmod(this.get('selected').get('path'), newPermission).then((response) => {
+ this.get('selected').set('permission', response.permission);
+ this.set('isUpdating', false);
+ this.send('close');
+ }, (error) => {
+ this.set('isUpdating', false);
+ this.send('close');
+ });
+ },
+
+ togglePermission: function(propertyName) {
+ Ember.run.later(() => {
+ this.set(propertyName, !this.get(propertyName));
+ });
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/popoverDelete.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/popoverDelete.js b/contrib/views/files/src/main/resources/ui/app/components/popoverDelete.js
deleted file mode 100644
index 2bd6fba..0000000
--- a/contrib/views/files/src/main/resources/ui/app/components/popoverDelete.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-var App = require('app');
-
-Em.BsPopoverComponent.reopen({
- willClearRender:function () {
- var triggers = this.triggers.split(' ');
-
- for (var i = triggers.length; i--;) {
- var trigger = triggers[i];
-
- if (trigger == 'click') {
- this.$element.off('click');
- } else if (trigger != 'manual') {
- var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus';
- var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur';
-
- this.$element.off(eventIn);
- this.$element.off(eventOut);
- }
- }
- }
-});
-
-App.PopoverDeleteComponent = Em.Component.extend({
- popover:Em.computed.alias('childViews.firstObject'),
- layoutName:'components/deletePopover',
- deleteForever:false,
- actions:{
- confirm:function (deleteForever) {
- this.sendAction('confirm',this.get('deleteForever'));
- },
- close:function () {
- this.set('popover.isVisible',false);
- }
- },
- didInsertElement:function () {
- $('body').on('click.popover', Em.run.bind(this,this.hideMultiply));
- },
- hideMultiply:function (e) {
- if (!this.$()) {
- return;
- }
- if (!this.$().is(e.target) && this.$().has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
- this.set('popover.isVisible',false);
- }
- },
- willClearRender:function () {
- this.get('popover').$element.off('click');
- $('body').off('click.popover');
- }
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/rename-modal.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/rename-modal.js b/contrib/views/files/src/main/resources/ui/app/components/rename-modal.js
new file mode 100644
index 0000000..09ae061
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/rename-modal.js
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+
+export default Ember.Component.extend(OperationModal, {
+ closeOnEscape: true,
+ hasError: false,
+ errorMessage: '',
+ isUpdating: false,
+ renameService: Ember.inject.service('file-rename'),
+ fileSelectionService: Ember.inject.service('files-selection'),
+ selectedFiles: Ember.computed.alias('fileSelectionService.files'),
+ selected: Ember.computed('selectedFiles', function() {
+ return this.get('selectedFiles').objectAt(0);
+ }),
+ selectionName: Ember.computed.oneWay('selected.name'),
+ hasErrorReset: Ember.observer('selectionName', 'selected.name', function() {
+ if (this.get('hasError') && (this.get('selectionName') !== this.get('selected.name'))) {
+ this.set('hasError', false);
+ }
+ }),
+
+ actions: {
+ didOpenModal: function() {
+ this.set('selectionName', this.get('selected.name'));
+ // This was required as the DOM may not be visible due to animation in bootstrap modal
+ Ember.run.later(() => {
+ this.$('input').focus();
+ }, 500);
+
+ },
+
+ rename: function() {
+ if(Ember.isBlank(this.get('selectionName'))) {
+ return false;
+ }
+
+ if(this.get('selected.name') === this.get('selectionName')) {
+ this.set('hasError', true);
+ this.set('errorMessage', 'Name should be different');
+ return false;
+ }
+ this.set('isUpdating', true);
+ this.get('renameService').rename(this.get('selected.path'), this.get('selectionName'))
+ .then((response) => {
+ this.set('isUpdating', false);
+ this.send('close');
+ this.sendAction('refreshAction');
+ }, (error) => {
+ this.set('isUpdating', false);
+ if(error.retry) {
+ this.set('hasError', true);
+ this.set('errorMessage', error.message);
+ } else {
+ this.send('close');
+ }
+ });
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/renameInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/renameInput.js b/contrib/views/files/src/main/resources/ui/app/components/renameInput.js
deleted file mode 100644
index 965cebd..0000000
--- a/contrib/views/files/src/main/resources/ui/app/components/renameInput.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-var App = require('app');
-
-App.RenameInputComponent = Ember.Component.extend({
- tagName:'span',
- layoutName:'components/renameInput',
- actions:{
- rename:function (opt) {
- var tmpName;
-
- switch (opt) {
- case 'edit': this.set('isRenaming',true); break;
- case 'cancel': this.set('isRenaming',false); break;
- case 'confirm':
- tmpName = this.get('tmpName');
- if (tmpName.length ===0) {
- break;
- }
- this.sendAction('confirm',this.get('filePath'),tmpName);
- this.set('isRenaming',false);
- break;
-
- default: this.toggleProperty('isRenaming');
- }
- }
- },
-
- /**
- * passed params
- */
- file:null,
- actionName:null,
- isRenaming:false,
-
- fileName:function () {
- var file = this.get('file');
- return (file instanceof DS.Model)?file.get('name'):file.substr(file.lastIndexOf('/')+1);
- }.property('file'),
-
- filePath:function () {
- var file = this.get('file');
- return (file instanceof DS.Model)?file.get('path'):file;
- }.property('file'),
-
- setTmpName:function () {
- if (this.get('isRenaming')) {
- this.set('tmpName',this.get('fileName'));
- } else {
- this.set('tmpName','');
- }
- }.observes('isRenaming'),
-
- onFileChange:function () {
- this.set('isRenaming',false);
- }.observes('file'),
-
- renameInputView: Em.TextField.extend({
- controller:null,
- didInsertElement:function () {
- var element = $(this.get('element'));
- element.focus().val(this.value);
- },
- keyUp: function(e) {
- var target = this.get('targetObject');
- if (e.keyCode==13) {
- return target.send('rename', 'confirm');
- }
-
- if (e.keyCode==27) {
- return target.send('rename', 'cancel');
- }
- }
- })
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/sortArrow.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/sortArrow.js b/contrib/views/files/src/main/resources/ui/app/components/sortArrow.js
deleted file mode 100644
index c680c41..0000000
--- a/contrib/views/files/src/main/resources/ui/app/components/sortArrow.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-var App = require('app');
-
-App.SortArrowComponent = Em.Component.extend({
- layout:Ember.Handlebars.compile('<i {{bind-attr class=":fa asc:fa-chevron-down:fa-chevron-up cur::fa-gr view.cur::fa-rotate-270" }} ></i>'),
- classNames:['pull-right'],
- tagName:'span',
- sPs:[],
- sA:false,
- sP:null,
- asc:true,
- cur:false,
- sorting:function () {
- var isSp = this.get('sPs.firstObject') == this.get('sP');
- this.setProperties({'asc':(isSp)?this.get('sA'):true,'cur':isSp});
- }.observes('sPs','sA').on('didInsertElement')
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/toggleContext.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/toggleContext.js b/contrib/views/files/src/main/resources/ui/app/components/toggleContext.js
deleted file mode 100644
index 10f1b52..0000000
--- a/contrib/views/files/src/main/resources/ui/app/components/toggleContext.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-var App = require('app');
-
-function _shake (element) {
- var l = 5;
- for ( var i = 0; i < 4; i++ ) {
- element.animate( (l>0) ? {'margin-left':(l=-l)+'px','padding-left':0}:{'padding-left':+(l=-l)+'px','margin-left':0}, 50, function (el) {
- element.css({'padding-left':0,'margin-left':0});
- });
- }
-}
-
-App.ToggleContextComponent = Em.Component.extend({
- didInsertElement:function () {
- var fileRow = this.$().parents('tr'),
- beforeHandler = Ember.run.bind(this, this.setContext),
- itemHandler = Ember.run.bind(this, this.itemHandler);
-
- fileRow.on('click',Ember.run.bind(this, this.openOnClick));
-
- fileRow.contextmenu({
- target:'#context-menu',
- before:beforeHandler,
- onItem:itemHandler
- });
- },
- setContext:function(e) {
- if (this.get('targetObject.isMoving')) {
- return false;
- }
- this.set('targetObject.parentController.targetContextMenu',this.get('targetObject'));
- return true;
- },
- itemHandler:function (t,e) {
- if (e.target.dataset.disabled) {
- return false;
- }
- },
- openOnClick:function (e) {
- if($(e.target).is('td') || $(e.target).hasClass('allow-open')){
- this.get('targetObject').send('open');
- }
- },
- willClearRender:function () {
- var fileRow = this.$().parents('tr');
- fileRow.off('click');
- fileRow.data('context').closemenu();
- fileRow.data('context').destroy();
- }
-});
-
-App.FileShakerComponent = Em.Component.extend({
- action:'',
- isValid:false,
- click:function () {
- if (this.get('isValid')) {
- this.sendAction('action');
- } else {
- _shake(this.$());
- }
- }
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/upload-file.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/upload-file.js b/contrib/views/files/src/main/resources/ui/app/components/upload-file.js
new file mode 100644
index 0000000..9da6854
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/components/upload-file.js
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+import OperationModal from '../mixins/operation-modal';
+import FileUploader from '../utils/file-uploader';
+
+export default Ember.Component.extend(OperationModal, {
+ modalEventBus: Ember.inject.service('modal-event-bus'),
+ fileOperationService: Ember.inject.service('file-operation'),
+ logger: Ember.inject.service('alert-messages'),
+ tagName: "span",
+ closeOnEscape: true,
+ name: 'ctx-uploader',
+ path: '',
+ isUploading: false,
+ uploadFileName: '',
+ uploadPercent: '0%',
+ uploadPercentStyle: Ember.computed('uploadPercent', function() {
+ var style = 'width: ' + this.get('uploadPercent') + ';';
+ return style.htmlSafe();
+ }),
+ didInitAttrs: function() {
+ this.get('modalEventBus').registerModal("ctx-uploader");
+ },
+ willDestroyElement() {
+ this.get('modalEventBus').resetModal("ctx-uploader");
+ },
+ setUploadPercent: function(percent) {
+ var intValue = Math.round(percent);
+ this.set('uploadPercent', `${intValue}%`);
+ },
+
+ setUploading: function(fileName) {
+ this.set('uploadFileName', fileName);
+ this.set('isUploading', true);
+ this.set('closeOnEscape', false);
+ },
+
+ actions: {
+ openModal : function() {
+ this.get('modalEventBus').showModal('ctx-uploader');
+ },
+ didOpenModal: function() {
+ this.set('isUploading', false);
+ this.set('uploadFileName', '');
+ this.set('closeOnEscape', true);
+ },
+
+ fileLoaded: function(file) {
+ var url = this.get('fileOperationService').getUploadUrl();
+ var uploader = FileUploader.create({
+ url: url
+ });
+ if(!Ember.isEmpty(file)) {
+ uploader.upload(file, {path: this.get('path')});
+ this.setUploading(file.name);
+ uploader.on('progress', (e) => {
+ this.setUploadPercent(e.percent);
+ });
+ uploader.on('didUpload', (e) => {
+ this.send('close');
+ this.sendAction('refreshAction');
+ });
+ uploader.on('didError', (jqXHR, textStatus, errorThrown) => {
+ var error = Ember.$.parseJSON(jqXHR.responseText);
+ this.get('logger').danger(`Failed to upload ${file.name} to ${this.get('path')}`, error);
+ this.send('close');
+ return false;
+ });
+ }
+
+ }
+
+ }
+});
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/components/uploader.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/uploader.js b/contrib/views/files/src/main/resources/ui/app/components/uploader.js
deleted file mode 100644
index f6e61c4..0000000
--- a/contrib/views/files/src/main/resources/ui/app/components/uploader.js
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-var App = require('app');
-
-App.FileUploaderComponent = Ember.Component.extend({
- didInsertElement:function () {
- var _this = this;
- this.uploader.reopen({
- sendAlert:function (e) {
- _this.sendAction('alert',e);
- }
- });
- this.fileInput.reopen({
- filesDidChange: function() {
- var files = this.get('files');
- if (!files) {
- this.set('parentView.files',null);
- this.set('parentView.controlInput.value','');
- this.set('value','');
- return;
- }
- var numFiles = files ? files.length : 1;
- var label = this.get('value').replace(/\\/g, '/').replace(/.*\//, '');
- var log = numFiles > 1 ? numFiles + ' files selected' : label;
-
- this.set('parentView.controlInput.value',log);
- this.set('parentView.files',files);
-
- }.observes('files')
- });
- },
- actions:{
- upload:function () {
- this.uploadFile();
- },
- clear:function () {
- this.set('fileInput.files',null);
- }
- },
- uploader: null,
- layoutName:'components/uploader',
- path:'',
- info:'',
- files:null,
- isFiles:function () {
- return !this.get('files.length');
- }.property('files'),
- uploadFile:function () {
- var path = this.get('path');
- var uploader = this.get('uploader');
- var uploadBtn = Ladda.create(this.uploadButton.get('element'));
- var reset = function () {
- uploadBtn.stop();
- this.send('clear');
- };
- if (!uploader.get('isUploading')) {
- if (!Ember.isEmpty(this.get('files'))) {
- var file = this.get('files')[0];
- uploadBtn.start();
- uploader.on('progress',function (e) {
- uploadBtn.setProgress(e.percent/100);
- });
- uploader.upload(file,{path:path}).finally(Em.run.bind(this,reset));
- }
- }
- },
- uploadButton: Em.View.createWithMixins(Ember.TargetActionSupport, {
- tagName:'button',
- target: Ember.computed.alias('controller'),
- classNames:['btn','ladda-button'],
- classNameBindings:['isFiles:hide','target.isError:btn-danger:btn-success'],
- attributeBindings: ["data-style","data-size"],
- action:'upload',
- click: function() {
- this.triggerAction();
- }
- }),
- fileInput : Ember.TextField.create({
- type: 'file',
- attributeBindings: ['multiple'],
- multiple: false,
- files:null,
- change: function(e) {
- var input = e.target;
- if (!Ember.isEmpty(input.files)) {
- this.set('files', input.files);
- }
- }
- }),
- controlInput:Ember.TextField.create({
- readonly:true,
- classNames:['form-control']
- })
-});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/config/files-columns.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/config/files-columns.js b/contrib/views/files/src/main/resources/ui/app/config/files-columns.js
new file mode 100644
index 0000000..4dce394
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/config/files-columns.js
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/*
+ Static configuration for the columns to be shown.
+*/
+var columnsConfig = [
+ {
+ title: 'Name',
+ key: 'name',
+ isVisible: true,
+ sortable: true,
+ sortOrder: 0,
+ columnClass: 'col-md-4 col-xs-4'
+ },
+ {
+ title: 'Size',
+ key: 'size',
+ isVisible: true,
+ sortable: true,
+ sortOrder: 0,
+ columnClass: 'col-md-1 col-xs-1'
+ },
+ {
+ title: 'Last Modified',
+ key: 'date',
+ isVisible: true,
+ sortable: true,
+ sortOrder: 0,
+ columnClass: 'col-md-2 col-xs-2'
+ },
+ {
+ title: 'Owner',
+ key: 'owner',
+ isVisible: true,
+ sortable: true,
+ sortOrder: 0,
+ columnClass: 'col-md-2 col-xs-2'
+ },
+ {
+ title: 'Group',
+ key: 'group',
+ isVisible: true,
+ sortable: true,
+ sortOrder: 0,
+ columnClass: 'col-md-1 col-xs-1'
+ },
+ {
+ title: 'Permission',
+ key: 'permission',
+ isVisible: true,
+ sortable: false,
+ sortOrder: 0,
+ columnClass: 'col-md-2 col-xs-2'
+ }
+];
+
+export default columnsConfig;
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/controllers/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/controllers/.gitkeep b/contrib/views/files/src/main/resources/ui/app/controllers/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/controllers/application.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/controllers/application.js b/contrib/views/files/src/main/resources/ui/app/controllers/application.js
new file mode 100644
index 0000000..29ab49c
--- /dev/null
+++ b/contrib/views/files/src/main/resources/ui/app/controllers/application.js
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 Ember from 'ember';
+
+export default Ember.Controller.extend({
+ firstLoad: true,
+ isLoading: false
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/controllers/chmodModal.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/controllers/chmodModal.js b/contrib/views/files/src/main/resources/ui/app/controllers/chmodModal.js
deleted file mode 100644
index a7170f7..0000000
--- a/contrib/views/files/src/main/resources/ui/app/controllers/chmodModal.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-var App = require('app');
-
-var _permissionsProp = function(n, l) {
- return function (arg,val) {
- if (arguments.length > 1) {
- this.set('permissions', this.replaceAt(n,(val)?l:'-'));
- return val;
- }
- return this.get('permissions')[n]===l;
- };
-};
-
-App.ChmodModalController = Em.ObjectController.extend({
- needs:['files'],
- classNames:'chmod-row',
- file:Em.computed.alias('content'),
- permissions:Em.computed.alias('file.permission'),
- usrR:_permissionsProp(1, 'r').property('permissions'),
- usrW:_permissionsProp(2, 'w').property('permissions'),
- usrE:_permissionsProp(3, 'x').property('permissions'),
- grpR:_permissionsProp(4, 'r').property('permissions'),
- grpW:_permissionsProp(5, 'w').property('permissions'),
- grpE:_permissionsProp(6, 'x').property('permissions'),
- otrR:_permissionsProp(7, 'r').property('permissions'),
- otrW:_permissionsProp(8, 'w').property('permissions'),
- otrE:_permissionsProp(9, 'x').property('permissions'),
- replaceAt:function (index,p) {
- var perm = this.get('permissions');
- return perm.substr(0, index) + p + perm.substr(index + p.length);
- }
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/controllers/error.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/controllers/error.js b/contrib/views/files/src/main/resources/ui/app/controllers/error.js
deleted file mode 100644
index efcc4de..0000000
--- a/contrib/views/files/src/main/resources/ui/app/controllers/error.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-App.ErrorController = Ember.ObjectController.extend({
- actions: {
- toggleStackTrace:function () {
- var value = this.get('isExpanded');
- this.set('isExpanded', !value);
- }
- },
-
- isExpanded: false,
-
- publicMessage:function () {
- var content = this.get('content');
- var text = content.statusText;
- if (content && content.responseText) {
- var json = JSON.parse(content.responseText);
- text = json.message;
- } else if (content && content.message) {
- text = content.message;
- }
- return text;
- }.property('content'),
- stackTrace:function () {
- var content = this.get('content');
- var trace = null;
- if (content && content.responseText) {
- var json = JSON.parse(content.responseText);
- trace = json.trace;
- }
- return trace;
- }.property('content')
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/b988562a/contrib/views/files/src/main/resources/ui/app/controllers/file.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/controllers/file.js b/contrib/views/files/src/main/resources/ui/app/controllers/file.js
deleted file mode 100644
index 88fa5fb..0000000
--- a/contrib/views/files/src/main/resources/ui/app/controllers/file.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-var App = require('app');
-
-App.FileController = Ember.ObjectController.extend({
- needs:['files'],
- actions:{
- confirmPreview:function (file) {
- this.downloadFile(file, "browse");
- },
- download:function (option) {
- this.downloadFile(this.get('content'), option);
- },
- preview:function (option) {
- this.send('showPreviewModal',this.get('content'));
- },
- showChmod:function () {
- this.send('showChmodModal',this.get('content'));
- },
- rename:function (opt,name) {
- var file = this.get('content'),
- path = file.get('path'),
- newPath;
-
- if (name === file.get('name') || Em.isEmpty(name)) {
- return this.set('isRenaming',!Em.isEmpty(name));
- }
-
- newPath = path.substring(0,path.lastIndexOf('/')+1)+name;
-
- this.store.move(file,newPath)
- .then(Em.run.bind(this,this.set,'isRenaming',false),Em.run.bind(this,this.sendAlert));
- },
- editName:function () {
- this.set('isRenaming',true);
- },
- open:function (file) {
- if (this.get('content.isDirectory')) {
- return this.transitionToRoute('files',{queryParams: {path: this.get('content.id')}});
- } else{
- //return this.send('download');
- return this.send('preview');
- }
- },
- deleteFile:function (deleteForever) {
- this.store
- .remove(this.get('content'),!deleteForever)
- .then(null,Em.run.bind(this,this.deleteErrorCallback,this.get('content')));
- }
- },
- selected:false,
- isRenaming:false,
- isMovingToTrash:false,
- chmodVisible:false,
- targetContextMenu:null,
- isPermissionsDirty:function () {
- var file = this.get('content');
- var diff = file.changedAttributes();
- return !!diff.permission;
- }.property('content.permission'),
- isMoving:function () {
- var movingFile = this.get('parentController.movingFile.path');
- var thisFile = this.get('content.id');
- return movingFile === thisFile;
- }.property('parentController.movingFile'),
-
- setSelected:function (controller,observer) {
- this.set('selected',this.get(observer));
- }.observes('content.selected'),
-
- renameSuccessCallback:function (record,error) {
- record.rollback();
- this.sendAlert(error);
- },
-
- dirInfo: Em.computed.alias('controllers.files.content.meta'),
-
- deleteErrorCallback:function (record,error) {
- this.get('parentController.model').pushRecord(record);
- this.send('showAlert',error);
- },
-
- sendAlert:function (error) {
- this.send('showAlert',error);
- },
- downloadFile: function(files, option) {
- var _this = this;
- this.store.linkFor([files], option, false, true).then(function(link) {
- var that = _this;
- Ember.$.get(link).done(function(data) {
- if(data.allowed) {
- that.store.linkFor([files],option).then(function (link) {
- window.location.href = link;
- },Em.run.bind(that,that.sendAlert));
- }
- }).fail(function(jqXHR, textStatus, errorThrown) {
- that.send('showAlert', jqXHR);
- });
- }, Em.run.bind(this,this.sendAlert));
- }
-});