summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/environments
diff options
context:
space:
mode:
authorAlfredo Sumaran <alfredo@gitlab.com>2017-04-04 18:41:01 +0000
committerAlfredo Sumaran <alfredo@gitlab.com>2017-04-04 18:41:01 +0000
commit30253183c66229b8d2f8e3e26f28470fb4bbc84a (patch)
tree1f7966d747709de2be913a84f9604622e6cd9cb1 /app/assets/javascripts/environments
parent81ac42bd5b1506b82628d7b07a886de4f2f38bfa (diff)
parentdb749d5d457e31d88e70a95ded35a850071359dd (diff)
downloadgitlab-ce-30253183c66229b8d2f8e3e26f28470fb4bbc84a.tar.gz
Merge branch '28732-expandable-folders' into 'master'
Resolve "Expandable folders for environments" Closes #28732 See merge request !10290
Diffstat (limited to 'app/assets/javascripts/environments')
-rw-r--r--app/assets/javascripts/environments/components/environment.js29
-rw-r--r--app/assets/javascripts/environments/components/environment_item.js30
-rw-r--r--app/assets/javascripts/environments/components/environments_table.js37
-rw-r--r--app/assets/javascripts/environments/services/environments_service.js5
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js70
5 files changed, 163 insertions, 8 deletions
diff --git a/app/assets/javascripts/environments/components/environment.js b/app/assets/javascripts/environments/components/environment.js
index 51aab8460f6..0518422e475 100644
--- a/app/assets/javascripts/environments/components/environment.js
+++ b/app/assets/javascripts/environments/components/environment.js
@@ -24,6 +24,7 @@ export default Vue.component('environment-component', {
state: store.state,
visibility: 'available',
isLoading: false,
+ isLoadingFolderContent: false,
cssContainerClass: environmentsData.cssClass,
endpoint: environmentsData.environmentsDataEndpoint,
canCreateDeployment: environmentsData.canCreateDeployment,
@@ -68,15 +69,21 @@ export default Vue.component('environment-component', {
this.fetchEnvironments();
eventHub.$on('refreshEnvironments', this.fetchEnvironments);
+ eventHub.$on('toggleFolder', this.toggleFolder);
},
beforeDestroyed() {
eventHub.$off('refreshEnvironments');
+ eventHub.$off('toggleFolder');
},
methods: {
- toggleRow(model) {
- return this.store.toggleFolder(model.name);
+ toggleFolder(folder, folderUrl) {
+ this.store.toggleFolder(folder);
+
+ if (!folder.isOpen) {
+ this.fetchChildEnvironments(folder, folderUrl);
+ }
},
/**
@@ -117,6 +124,21 @@ export default Vue.component('environment-component', {
new Flash('An error occurred while fetching the environments.');
});
},
+
+ fetchChildEnvironments(folder, folderUrl) {
+ this.isLoadingFolderContent = true;
+
+ this.service.getFolderContent(folderUrl)
+ .then(resp => resp.json())
+ .then((response) => {
+ this.store.setfolderContent(folder, response.environments);
+ this.isLoadingFolderContent = false;
+ })
+ .catch(() => {
+ this.isLoadingFolderContent = false;
+ new Flash('An error occurred while fetching the environments.');
+ });
+ },
},
template: `
@@ -179,7 +201,8 @@ export default Vue.component('environment-component', {
:environments="state.environments"
:can-create-deployment="canCreateDeploymentParsed"
:can-read-environment="canReadEnvironmentParsed"
- :service="service"/>
+ :service="service"
+ :is-loading-folder-content="isLoadingFolderContent" />
</div>
<table-pagination v-if="state.paginationInformation && state.paginationInformation.totalPages > 1"
diff --git a/app/assets/javascripts/environments/components/environment_item.js b/app/assets/javascripts/environments/components/environment_item.js
index 9c196562c6c..e44d93a30c7 100644
--- a/app/assets/javascripts/environments/components/environment_item.js
+++ b/app/assets/javascripts/environments/components/environment_item.js
@@ -7,6 +7,7 @@ import RollbackComponent from './environment_rollback';
import TerminalButtonComponent from './environment_terminal_button';
import MonitoringButtonComponent from './environment_monitoring';
import CommitComponent from '../../vue_shared/components/commit';
+import eventHub from '../event_hub';
/**
* Envrionment Item Component
@@ -410,7 +411,6 @@ export default {
folderUrl() {
return `${window.location.pathname}/folders/${this.model.folderName}`;
},
-
},
/**
@@ -428,15 +428,37 @@ export default {
return true;
},
+ methods: {
+ onClickFolder() {
+ eventHub.$emit('toggleFolder', this.model, this.folderUrl);
+ },
+ },
+
template: `
- <tr>
+ <tr :class="{ 'js-child-row': model.isChildren }">
<td>
<a v-if="!model.isFolder"
class="environment-name"
+ :class="{ 'prepend-left-default': model.isChildren }"
:href="environmentPath">
{{model.name}}
</a>
- <a v-else class="folder-name" :href="folderUrl">
+ <span v-else
+ class="folder-name"
+ @click="onClickFolder"
+ role="button">
+
+ <span class="folder-icon">
+ <i
+ v-show="model.isOpen"
+ class="fa fa-caret-down"
+ aria-hidden="true" />
+ <i
+ v-show="!model.isOpen"
+ class="fa fa-caret-right"
+ aria-hidden="true"/>
+ </span>
+
<span class="folder-icon">
<i class="fa fa-folder" aria-hidden="true"></i>
</span>
@@ -448,7 +470,7 @@ export default {
<span class="badge">
{{model.size}}
</span>
- </a>
+ </span>
</td>
<td class="deployment-column">
diff --git a/app/assets/javascripts/environments/components/environments_table.js b/app/assets/javascripts/environments/components/environments_table.js
index 338dff40bc9..5e6af3a1d45 100644
--- a/app/assets/javascripts/environments/components/environments_table.js
+++ b/app/assets/javascripts/environments/components/environments_table.js
@@ -31,6 +31,18 @@ export default {
type: Object,
required: true,
},
+
+ isLoadingFolderContent: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+
+ methods: {
+ folderUrl(model) {
+ return `${window.location.pathname}/folders/${model.folderName}`;
+ },
},
template: `
@@ -53,6 +65,31 @@ export default {
:can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
:service="service"></tr>
+
+ <template v-if="model.isFolder && model.isOpen && model.children && model.children.length > 0">
+ <tr v-if="isLoadingFolderContent">
+ <td colspan="6" class="text-center">
+ <i class="fa fa-spin fa-spinner fa-2x" aria-hidden="true"/>
+ </td>
+ </tr>
+
+ <template v-else>
+ <tr is="environment-item"
+ v-for="children in model.children"
+ :model="children"
+ :can-create-deployment="canCreateDeployment"
+ :can-read-environment="canReadEnvironment"
+ :service="service"></tr>
+
+ <tr>
+ <td colspan="6" class="text-center">
+ <a :href="folderUrl(model)" class="btn btn-default">
+ Show all
+ </a>
+ </td>
+ </tr>
+ </template>
+ </template>
</template>
</tbody>
</table>
diff --git a/app/assets/javascripts/environments/services/environments_service.js b/app/assets/javascripts/environments/services/environments_service.js
index 07040bf0d73..8adb53ea86d 100644
--- a/app/assets/javascripts/environments/services/environments_service.js
+++ b/app/assets/javascripts/environments/services/environments_service.js
@@ -7,6 +7,7 @@ Vue.use(VueResource);
export default class EnvironmentsService {
constructor(endpoint) {
this.environments = Vue.resource(endpoint);
+ this.folderResults = 3;
}
get(scope, page) {
@@ -16,4 +17,8 @@ export default class EnvironmentsService {
postAction(endpoint) {
return Vue.http.post(endpoint, {}, { emulateJSON: true });
}
+
+ getFolderContent(folderUrl) {
+ return Vue.http.get(`${folderUrl}.json?per_page=${this.folderResults}`);
+ }
}
diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js
index 3c3084f3b78..158e7922e3c 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js
+++ b/app/assets/javascripts/environments/stores/environments_store.js
@@ -38,7 +38,12 @@ export default class EnvironmentsStore {
let filtered = {};
if (env.size > 1) {
- filtered = Object.assign({}, env, { isFolder: true, folderName: env.name });
+ filtered = Object.assign({}, env, {
+ isFolder: true,
+ folderName: env.name,
+ isOpen: false,
+ children: [],
+ });
}
if (env.latest) {
@@ -85,4 +90,67 @@ export default class EnvironmentsStore {
this.state.stoppedCounter = count;
return count;
}
+
+ /**
+ * Toggles folder open property for the given folder.
+ *
+ * @param {Object} folder
+ * @return {Array}
+ */
+ toggleFolder(folder) {
+ return this.updateFolder(folder, 'isOpen', !folder.isOpen);
+ }
+
+ /**
+ * Updates the folder with the received environments.
+ *
+ *
+ * @param {Object} folder Folder to update
+ * @param {Array} environments Received environments
+ * @return {Object}
+ */
+ setfolderContent(folder, environments) {
+ const updatedEnvironments = environments.map((env) => {
+ let updated = env;
+
+ if (env.latest) {
+ updated = Object.assign({}, env, env.latest);
+ delete updated.latest;
+ } else {
+ updated = env;
+ }
+
+ updated.isChildren = true;
+
+ return updated;
+ });
+
+ return this.updateFolder(folder, 'children', updatedEnvironments);
+ }
+
+ /**
+ * Given a folder a prop and a new value updates the correct folder.
+ *
+ * @param {Object} folder
+ * @param {String} prop
+ * @param {String|Boolean|Object|Array} newValue
+ * @return {Array}
+ */
+ updateFolder(folder, prop, newValue) {
+ const environments = this.state.environments;
+
+ const updatedEnvironments = environments.map((env) => {
+ const updateEnv = Object.assign({}, env);
+ if (env.isFolder && env.id === folder.id) {
+ updateEnv[prop] = newValue;
+ }
+
+ return updateEnv;
+ });
+
+ this.state.environments = updatedEnvironments;
+
+ return updatedEnvironments;
+ }
+
}