mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-16 15:58:39 -05:00
refactor projects list, clean up dependencies and old list generators and factory methods
This commit is contained in:
committed by
John Mitchell
parent
c95c2a4580
commit
92ac3054c6
@@ -0,0 +1,19 @@
|
||||
function IndexProjectsController ($scope, strings, dataset) {
|
||||
const vm = this;
|
||||
vm.strings = strings;
|
||||
vm.count = dataset.data.count;
|
||||
|
||||
$scope.$on('updateCount', (e, count) => {
|
||||
if (count) {
|
||||
vm.count = count;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
IndexProjectsController.$inject = [
|
||||
'$scope',
|
||||
'ProjectsStrings',
|
||||
'Dataset',
|
||||
];
|
||||
|
||||
export default IndexProjectsController;
|
||||
@@ -0,0 +1,9 @@
|
||||
import ProjectsStrings from './projects.strings';
|
||||
|
||||
const MODULE_NAME = 'at.features.projects';
|
||||
|
||||
angular
|
||||
.module(MODULE_NAME, [])
|
||||
.service('ProjectsStrings', ProjectsStrings);
|
||||
|
||||
export default MODULE_NAME;
|
||||
@@ -0,0 +1,13 @@
|
||||
<div ui-view="scheduler"></div>
|
||||
<div ui-view="form"></div>
|
||||
<at-panel ng-cloak id="htmlTemplate">
|
||||
<div ng-if="$state.includes('projects')">
|
||||
<at-panel-heading hide-dismiss="true">
|
||||
{{:: vm.strings.get('list.PANEL_TITLE') }}
|
||||
<div class="at-Panel-headingTitleBadge" ng-show="vm.count">
|
||||
{{ vm.count }}
|
||||
</div>
|
||||
</at-panel-heading>
|
||||
</div>
|
||||
<div ui-view="projectsList"></div>
|
||||
</at-panel>
|
||||
@@ -0,0 +1,53 @@
|
||||
function ProjectsStrings (BaseString) {
|
||||
BaseString.call(this, 'projects');
|
||||
|
||||
const { t } = this;
|
||||
const ns = this.projects;
|
||||
|
||||
ns.list = {
|
||||
PANEL_TITLE: t.s('PROJECTS'),
|
||||
ROW_ITEM_LABEL_REVISION: t.s('REVISION'),
|
||||
ROW_ITEM_LABEL_ORGANIZATION: t.s('ORGANIZATION'),
|
||||
ROW_ITEM_LABEL_MODIFIED: t.s('LAST MODIFIED'),
|
||||
ROW_ITEM_LABEL_USED: t.s('LAST USED'),
|
||||
};
|
||||
|
||||
ns.update = {
|
||||
GET_LATEST: t.s('Get latest SCM revision'),
|
||||
UPDATE_RUNNING: t.s('SCM update currently running'),
|
||||
MANUAL_PROJECT_NO_UPDATE: t.s('Manual projects do not require an SCM update'),
|
||||
CANCEL_UPDATE_REQUEST: t.s('Your request to cancel the update was submitted to the task manager.'),
|
||||
NO_UPDATE_INFO: t.s('There is no SCM update information available for this project. An update has not yet been completed. If you have not already done so, start an update for this project.'),
|
||||
NO_PROJ_SCM_CONFIG: t.s('The selected project is not configured for SCM. To configure for SCM, edit the project and provide SCM settings, and then run an update.'),
|
||||
NO_ACCESS_OR_COMPLETED_UPDATE: t.s('Either you do not have access or the SCM update process completed'),
|
||||
NO_RUNNING_UPDATE: t.s('An SCM update does not appear to be running for project: '),
|
||||
};
|
||||
|
||||
ns.alert = {
|
||||
NO_UPDATE: t.s('No Updates Available'),
|
||||
UPDATE_CANCEL: t.s('SCM Update Cancel'),
|
||||
CANCEL_NOT_ALLOWED: t.s('Cancel Not Allowed'),
|
||||
NO_SCM_CONFIG: t.s('No SCM Configuration'),
|
||||
UPDATE_NOT_FOUND: t.s('Update Not Found'),
|
||||
};
|
||||
|
||||
ns.status = {
|
||||
NOT_CONFIG: t.s('Not configured for SCM'),
|
||||
NEVER_UPDATE: t.s('No SCM updates have run for this project'),
|
||||
UPDATE_QUEUED: t.s('Update queued. Click for details'),
|
||||
UPDATE_RUNNING: t.s('Update running. Click for details'),
|
||||
UPDATE_SUCCESS: t.s('Update succeeded. Click for details'),
|
||||
UPDATE_FAILED: t.s('Update failed. Click for details'),
|
||||
UPDATE_MISSING: t.s('Update missing. Click for details'),
|
||||
UPDATE_CANCELED: t.s('Update canceled. Click for details'),
|
||||
};
|
||||
|
||||
ns.error = {
|
||||
HEADER: this.error.HEADER,
|
||||
CALL: this.error.CALL,
|
||||
};
|
||||
}
|
||||
|
||||
ProjectsStrings.$inject = ['BaseStringService'];
|
||||
|
||||
export default ProjectsStrings;
|
||||
@@ -0,0 +1,439 @@
|
||||
/** ***********************************************
|
||||
* Copyright (c) 2018 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
************************************************ */
|
||||
|
||||
const mapChoices = choices => Object.assign(...choices.map(([k, v]) => ({ [k]: v.toUpperCase() })));
|
||||
|
||||
function projectsListController (
|
||||
$filter, $scope, $rootScope, $state, $log, Dataset, Alert, Rest,
|
||||
ProcessErrors, resolvedModels, strings, Wait, ngToast,
|
||||
Prompt, GetBasePath, qs, ProjectUpdate,
|
||||
) {
|
||||
const vm = this || {};
|
||||
const [ProjectModel] = resolvedModels;
|
||||
$scope.canAdd = ProjectModel.options('actions.POST');
|
||||
|
||||
vm.strings = strings;
|
||||
vm.scm_choices = ProjectModel.options('actions.GET.scm_type.choices');
|
||||
vm.projectTypes = mapChoices(vm.scm_choices);
|
||||
|
||||
// smart-search
|
||||
vm.list = {
|
||||
iterator: 'project',
|
||||
name: 'projects',
|
||||
basePath: 'projects',
|
||||
};
|
||||
vm.dataset = Dataset.data;
|
||||
vm.projects = Dataset.data.results;
|
||||
// build tooltips
|
||||
_.forEach(vm.projects, buildTooltips);
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
// when a project is added/deleted, rebuild tooltips
|
||||
$scope.$watchCollection('vm.projects', () => {
|
||||
_.forEach(vm.projects, buildTooltips);
|
||||
});
|
||||
// show active item in the list
|
||||
$scope.$watch('$state.params', () => {
|
||||
const projectId = _.get($state.params, 'project_id');
|
||||
if ((projectId)) {
|
||||
vm.activeId = parseInt($state.params.project_id, 10);
|
||||
} else {
|
||||
vm.activeId = '';
|
||||
}
|
||||
}, true);
|
||||
|
||||
$scope.$on('ws-jobs', (e, data) => {
|
||||
$log.debug(data);
|
||||
if (vm.projects) {
|
||||
// Assuming we have a list of projects available
|
||||
const project = vm.projects.find((p) => p.id === data.project_id);
|
||||
if (project) {
|
||||
// And we found the affected project
|
||||
$log.debug(`Received event for project: ${project.name}`);
|
||||
$log.debug(`Status changed to: ${data.status}`);
|
||||
if (data.status === 'successful' || data.status === 'failed' || data.status === 'canceled') {
|
||||
reloadList();
|
||||
} else {
|
||||
project.scm_update_tooltip = vm.strings.get('update.UPDATE_RUNNING');
|
||||
}
|
||||
project.status = data.status;
|
||||
buildTooltips(project);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ($scope.removeGoTojobResults) {
|
||||
$scope.removeGoTojobResults();
|
||||
}
|
||||
|
||||
$scope.removeGoTojobResults = $scope.$on('GoTojobResults', (e, data) => {
|
||||
if (data.summary_fields.current_update || data.summary_fields.last_update) {
|
||||
Wait('start');
|
||||
// Grab the id from summary_fields
|
||||
const updateJobid = (data.summary_fields.current_update) ?
|
||||
data.summary_fields.current_update.id : data.summary_fields.last_update.id;
|
||||
|
||||
$state.go('output', { id: updateJobid, type: 'project' }, { reload: true });
|
||||
} else {
|
||||
Alert(vm.strings.get('alert.NO_UPDATE'), vm.strings.get('update.NO_UPDATE_INFO'), 'alert-info');
|
||||
}
|
||||
});
|
||||
|
||||
if ($scope.removeCancelUpdate) {
|
||||
$scope.removeCancelUpdate();
|
||||
}
|
||||
|
||||
$scope.removeCancelUpdate = $scope.$on('Cancel_Update', (e, url) => {
|
||||
// Cancel the project update process
|
||||
Rest.setUrl(url);
|
||||
Rest.post()
|
||||
.then(() => {
|
||||
Alert(vm.strings.get('alert.UPDATE_CANCEL'), vm.strings.get('update.CANCEL_UPDATE_REQUEST'), 'alert-info');
|
||||
})
|
||||
.catch(createErrorHandler(url, 'POST'));
|
||||
});
|
||||
|
||||
if ($scope.removeCheckCancel) {
|
||||
$scope.removeCheckCancel();
|
||||
}
|
||||
|
||||
$scope.removeCheckCancel = $scope.$on('Check_Cancel', (e, projectData) => {
|
||||
// Check that we 'can' cancel the update
|
||||
const url = projectData.related.cancel;
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.then(({ data }) => {
|
||||
if (data.can_cancel) {
|
||||
$scope.$emit('Cancel_Update', url);
|
||||
} else {
|
||||
Alert(vm.strings.get('alert.CANCEL_NOT_ALLOWED'), vm.strings.get('update.NO_ACCESS_OR_COMPLETED_UPDATE'), 'alert-info', null, null, null, null, true);
|
||||
}
|
||||
})
|
||||
.catch(createErrorHandler(url, 'GET'));
|
||||
});
|
||||
|
||||
vm.showSCMStatus = (id) => {
|
||||
// Refresh the project list
|
||||
const project = vm.projects.find((p) => p.id === id);
|
||||
|
||||
if ((!project.scm_type) || project.scm_type === 'Manual') {
|
||||
Alert(vm.strings.get('alert.NO_SCM_CONFIG'), vm.strings.get('update.NO_PROJ_SCM_CONFIG'), 'alert-info');
|
||||
} else {
|
||||
// Refresh what we have in memory
|
||||
// to insure we're accessing the most recent status record
|
||||
Rest.setUrl(project.url);
|
||||
Rest.get()
|
||||
.then(({ data }) => {
|
||||
$scope.$emit('GoTojobResults', data);
|
||||
})
|
||||
.catch(createErrorHandler(project.url, 'GET'));
|
||||
}
|
||||
};
|
||||
|
||||
vm.getLastModified = project => {
|
||||
const modified = _.get(project, 'modified');
|
||||
|
||||
if (!modified) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const html = $filter('longDate')(modified);
|
||||
|
||||
// NEED api to add field project.summary_fields.modified_by
|
||||
|
||||
// const { username, id } = _.get(project, 'summary_fields.modified_by', {});
|
||||
|
||||
// if (username && id) {
|
||||
// html += ` by <a href="/#/users/${id}">${$filter('sanitize')(username)}</a>`;
|
||||
// }
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
vm.getLastUsed = project => {
|
||||
const modified = _.get(project, 'last_job_run');
|
||||
|
||||
if (!modified) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const html = $filter('longDate')(modified);
|
||||
|
||||
// NEED api to add last_job user information such as launch_by
|
||||
|
||||
// const { id } = _.get(project, 'summary_fields.last_job', {});
|
||||
// if (id) {
|
||||
// html += ` by <a href="/#/jobs/project/${id}">
|
||||
// ${$filter('sanitize')('placehoder')}</a>`;
|
||||
// }
|
||||
return html;
|
||||
};
|
||||
|
||||
vm.copyProject = project => {
|
||||
Wait('start');
|
||||
ProjectModel
|
||||
.create('get', project.id)
|
||||
.then(model => model.copy())
|
||||
.then((copiedProj) => {
|
||||
ngToast.success({
|
||||
content: `
|
||||
<div class="Toast-wrapper">
|
||||
<div class="Toast-icon">
|
||||
<i class="fa fa-check-circle Toast-successIcon"></i>
|
||||
</div>
|
||||
<div>
|
||||
${vm.strings.get('SUCCESSFUL_CREATION', copiedProj.name)}
|
||||
</div>
|
||||
</div>`,
|
||||
dismissButton: false,
|
||||
dismissOnTimeout: true
|
||||
});
|
||||
$state.go('.', null, { reload: true });
|
||||
})
|
||||
.catch(createErrorHandler('copy project', 'GET'))
|
||||
.finally(() => Wait('stop'));
|
||||
};
|
||||
|
||||
vm.deleteProject = (id, name) => {
|
||||
const action = () => {
|
||||
$('#prompt-modal').modal('hide');
|
||||
Wait('start');
|
||||
ProjectModel
|
||||
.request('delete', id)
|
||||
.then(() => {
|
||||
let reloadListStateParams = null;
|
||||
|
||||
if (vm.projects.length === 1
|
||||
&& $state.params.project_search
|
||||
&& _.has($state, 'params.project_search.page')
|
||||
&& $state.params.project_search.page !== '1') {
|
||||
reloadListStateParams = _.cloneDeep($state.params);
|
||||
reloadListStateParams.project_search.page =
|
||||
(parseInt(reloadListStateParams.project_search.page, 10) - 1).toString();
|
||||
}
|
||||
|
||||
if (parseInt($state.params.project_id, 10) === id) {
|
||||
$state.go('^', reloadListStateParams, { reload: true });
|
||||
} else {
|
||||
$state.go('.', reloadListStateParams, { reload: true });
|
||||
}
|
||||
})
|
||||
.catch(createErrorHandler(`${ProjectModel.path}${id}/`, 'DELETE'))
|
||||
.finally(() => {
|
||||
Wait('stop');
|
||||
});
|
||||
};
|
||||
|
||||
ProjectModel.getDependentResourceCounts(id)
|
||||
.then((counts) => {
|
||||
const invalidateRelatedLines = [];
|
||||
let deleteModalBody = `<div class="Prompt-bodyQuery">${vm.strings.get('deleteResource.CONFIRM', 'project')}</div>`;
|
||||
|
||||
counts.forEach(countObj => {
|
||||
if (countObj.count && countObj.count > 0) {
|
||||
invalidateRelatedLines.push(`<div><span class="Prompt-warningResourceTitle">${countObj.label}</span><span class="badge List-titleBadge">${countObj.count}</span></div>`);
|
||||
}
|
||||
});
|
||||
|
||||
if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
|
||||
deleteModalBody = `<div class="Prompt-bodyQuery">${vm.strings.get('deleteResource.USED_BY', 'project')} ${vm.strings.get('deleteResource.CONFIRM', 'project')}</div>`;
|
||||
invalidateRelatedLines.forEach(invalidateRelatedLine => {
|
||||
deleteModalBody += invalidateRelatedLine;
|
||||
});
|
||||
}
|
||||
|
||||
Prompt({
|
||||
hdr: vm.strings.get('DELETE'),
|
||||
resourceName: $filter('sanitize')(name),
|
||||
body: deleteModalBody,
|
||||
action,
|
||||
actionText: vm.strings.get('DELETE'),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
vm.cancelUpdate = (project) => {
|
||||
project.pending_cancellation = true;
|
||||
Rest.setUrl(GetBasePath('projects') + project.id);
|
||||
Rest.get()
|
||||
.then(({ data }) => {
|
||||
if (data.related.current_update) {
|
||||
cancelSCMUpdate(data);
|
||||
} else {
|
||||
Alert(vm.strings.get('update.UPDATE_NOT_FOUND'), vm.strings.get('update.NO_RUNNING_UPDATE') + project.name, 'alert-info', undefined, undefined, undefined, undefined, true);
|
||||
}
|
||||
})
|
||||
.catch(createErrorHandler('get project', 'GET'));
|
||||
};
|
||||
|
||||
vm.SCMUpdate = (id, event) => {
|
||||
try {
|
||||
$(event.target).tooltip('hide');
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
vm.projects.forEach((project) => {
|
||||
if (project.id === id) {
|
||||
if (project.scm_type === 'Manual' || (!project.scm_type)) {
|
||||
// Do not respond. Button appears greyed out as if it is disabled.
|
||||
// Not disabled though, because we need mouse over event
|
||||
// to work. So user can click, but we just won't do anything.
|
||||
// Alert('Missing SCM Setup', 'Before running an SCM update,
|
||||
// edit the project and provide the SCM access information.', 'alert-info');
|
||||
} else if (project.status === 'updating' || project.status === 'running' || project.status === 'pending') {
|
||||
// Alert('Update in Progress', 'The SCM update process is running.
|
||||
// Use the Refresh button to monitor the status.', 'alert-info');
|
||||
} else {
|
||||
ProjectUpdate({ scope: $scope, project_id: project.id });
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function buildTooltips (project) {
|
||||
project.statusIcon = getStatusIcon(project);
|
||||
project.statusTip = getStatusTooltip(project);
|
||||
project.scm_update_tooltip = vm.strings.get('update.GET_LATEST');
|
||||
project.scm_update_disabled = false;
|
||||
|
||||
if (project.status === 'pending' || project.status === 'waiting') {
|
||||
project.scm_update_disabled = true;
|
||||
}
|
||||
|
||||
if (project.status === 'failed' && project.summary_fields.last_update && project.summary_fields.last_update.status === 'canceled') {
|
||||
project.statusTip = vm.strings.get('status.UPDATE_CANCELED');
|
||||
project.scm_update_disabled = true;
|
||||
}
|
||||
|
||||
if (project.status === 'running' || project.status === 'updating') {
|
||||
project.scm_update_tooltip = vm.strings.get('update.UPDATE_RUNNING');
|
||||
project.scm_update_disabled = true;
|
||||
}
|
||||
|
||||
if (project.scm_type === 'manual') {
|
||||
project.statusIcon = 'none';
|
||||
project.statusTip = vm.strings.get('status.NOT_CONFIG');
|
||||
project.scm_update_tooltip = vm.strings.get('update.MANUAL_PROJECT_NO_UPDATE');
|
||||
project.scm_update_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
function cancelSCMUpdate (projectData) {
|
||||
Rest.setUrl(projectData.related.current_update);
|
||||
Rest.get()
|
||||
.then(({ data }) => {
|
||||
$scope.$emit('Check_Cancel', data);
|
||||
})
|
||||
.catch(createErrorHandler(projectData.related.current_update, 'GET'));
|
||||
}
|
||||
|
||||
function reloadList () {
|
||||
Wait('start');
|
||||
const path = GetBasePath(vm.list.basePath) || GetBasePath(vm.list.name);
|
||||
qs.search(path, $state.params.project_search)
|
||||
.then((searchResponse) => {
|
||||
vm.dataset = searchResponse.data;
|
||||
vm.projects = vm.dataset.results;
|
||||
})
|
||||
.finally(() => Wait('stop'));
|
||||
}
|
||||
|
||||
function createErrorHandler (path, action) {
|
||||
return ({ data, status }) => {
|
||||
const hdr = strings.get('error.HEADER');
|
||||
const msg = strings.get('error.CALL', { path, action, status });
|
||||
ProcessErrors($scope, data, status, null, { hdr, msg });
|
||||
};
|
||||
}
|
||||
|
||||
function getStatusIcon (project) {
|
||||
let icon = 'none';
|
||||
switch (project.status) {
|
||||
case 'n/a':
|
||||
case 'ok':
|
||||
case 'never updated':
|
||||
icon = 'none';
|
||||
break;
|
||||
case 'pending':
|
||||
case 'waiting':
|
||||
case 'new':
|
||||
icon = 'none';
|
||||
break;
|
||||
case 'updating':
|
||||
case 'running':
|
||||
icon = 'running';
|
||||
break;
|
||||
case 'successful':
|
||||
icon = 'success';
|
||||
break;
|
||||
case 'failed':
|
||||
case 'missing':
|
||||
case 'canceled':
|
||||
icon = 'error';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
function getStatusTooltip (project) {
|
||||
let tooltip = '';
|
||||
switch (project.status) {
|
||||
case 'n/a':
|
||||
case 'ok':
|
||||
case 'never updated':
|
||||
tooltip = vm.strings.get('status.NEVER_UPDATE');
|
||||
break;
|
||||
case 'pending':
|
||||
case 'waiting':
|
||||
case 'new':
|
||||
tooltip = vm.strings.get('status.UPDATE_QUEUED');
|
||||
break;
|
||||
case 'updating':
|
||||
case 'running':
|
||||
tooltip = vm.strings.get('status.UPDATE_RUNNING');
|
||||
break;
|
||||
case 'successful':
|
||||
tooltip = vm.strings.get('status.UPDATE_SUCCESS');
|
||||
break;
|
||||
case 'failed':
|
||||
tooltip = vm.strings.get('status.UPDATE_FAILED');
|
||||
break;
|
||||
case 'missing':
|
||||
tooltip = vm.strings.get('status.UPDATE_MISSING');
|
||||
break;
|
||||
case 'canceled':
|
||||
tooltip = vm.strings.get('status.UPDATE_CANCELED');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return tooltip;
|
||||
}
|
||||
}
|
||||
|
||||
projectsListController.$inject = [
|
||||
'$filter',
|
||||
'$scope',
|
||||
'$rootScope',
|
||||
'$state',
|
||||
'$log',
|
||||
'Dataset',
|
||||
'Alert',
|
||||
'Rest',
|
||||
'ProcessErrors',
|
||||
'resolvedModels',
|
||||
'ProjectsStrings',
|
||||
'Wait',
|
||||
'ngToast',
|
||||
'Prompt',
|
||||
'GetBasePath',
|
||||
'QuerySet',
|
||||
'ProjectUpdate',
|
||||
];
|
||||
|
||||
export default projectsListController;
|
||||
@@ -0,0 +1,91 @@
|
||||
<at-panel-body>
|
||||
<div class="at-List-toolbar">
|
||||
<smart-search
|
||||
class="at-List-search"
|
||||
django-model="projects"
|
||||
base-path="projects"
|
||||
iterator="project"
|
||||
list="vm.list"
|
||||
collection="vm.projects"
|
||||
dataset="vm.dataset"
|
||||
search-tags="searchTags">
|
||||
</smart-search>
|
||||
<div class="at-List-toolbarAction" ng-show="canAdd">
|
||||
<button
|
||||
type="button"
|
||||
class="at-Button--add"
|
||||
id="button-add"
|
||||
ui-sref="projects.add">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<at-list results="vm.projects">
|
||||
<at-row ng-repeat="project in vm.projects"
|
||||
ng-class="{'at-Row--active': (project.id === vm.activeId)}">
|
||||
<div class="at-Row-items">
|
||||
<at-row-item
|
||||
status="{{ project.statusIcon }}"
|
||||
status-tip="{{ project.statusTip }}"
|
||||
status-click="vm.showSCMStatus(project.id)"
|
||||
header-value="{{ project.name }}"
|
||||
header-link="/#/projects/{{ project.id }}"
|
||||
header-tag="{{ vm.projectTypes[project.scm_type] }}">
|
||||
</at-row-item>
|
||||
<div class="at-RowItem" ng-if="project.scm_revision">
|
||||
<div class="at-RowItem-label">
|
||||
{{ :: vm.strings.get('list.ROW_ITEM_LABEL_REVISION') }}
|
||||
</div>
|
||||
<at-truncate string="{{ project.scm_revision }}" maxLength="7"></at-truncate>
|
||||
</div>
|
||||
<at-row-item
|
||||
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_ORGANIZATION')}}"
|
||||
value="{{ project.summary_fields.organization.name }}"
|
||||
value-link="/#/organizations/{{ project.organization }}">
|
||||
</at-row-item>
|
||||
<at-row-item
|
||||
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_MODIFIED') }}"
|
||||
value-bind-html="{{ vm.getLastModified(project) }}">
|
||||
</at-row-item>
|
||||
<at-row-item
|
||||
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_USED') }}"
|
||||
value-bind-html="{{ vm.getLastUsed(project) }}">
|
||||
</at-row-item>
|
||||
</div>
|
||||
<div class="at-Row-actions">
|
||||
<div aw-tool-tip="{{ project.scm_update_tooltip }}"
|
||||
data-tip-watch="project.scm_update_tooltip"
|
||||
data-placement="top">
|
||||
<div class="at-RowAction"
|
||||
ng-class="{'at-RowAction--disabled': project.scm_update_disabled }"
|
||||
ng-click="vm.SCMUpdate(project.id, $event)"
|
||||
ng-show="project.summary_fields.user_capabilities.start">
|
||||
<i class="fa fa-refresh"></i>
|
||||
</div>
|
||||
</div>
|
||||
<at-row-action icon="fa-copy" ng-click="vm.copyProject(project)"
|
||||
ng-show="project.summary_fields.user_capabilities.copy">
|
||||
</at-row-action>
|
||||
<at-row-action icon="fa-trash" ng-click="vm.deleteProject(project.id, project.name)"
|
||||
ng-show="(project.status !== 'updating'
|
||||
&& project.status !== 'running'
|
||||
&& project.status !== 'pending'
|
||||
&& project.status !== 'waiting')
|
||||
&& project.summary_fields.user_capabilities.delete">
|
||||
</at-row-action>
|
||||
<at-row-action icon="fa-minus-circle" ng-click="vm.cancelUpdate(project)"
|
||||
ng-show="(project.status == 'updating'
|
||||
|| project.status == 'running'
|
||||
|| project.status == 'pending'
|
||||
|| project.status == 'waiting')
|
||||
&& project.summary_fields.user_capabilities.start">
|
||||
</at-row-action>
|
||||
</div>
|
||||
</at-row>
|
||||
</at-list>
|
||||
<paginate
|
||||
collection="vm.projects"
|
||||
dataset="vm.dataset"
|
||||
iterator="project"
|
||||
base-path="projects">
|
||||
</paginate>
|
||||
</at-panel-body>
|
||||
@@ -0,0 +1,91 @@
|
||||
import { N_ } from '../../../src/i18n';
|
||||
import projectsListController from '../projectsList.controller';
|
||||
import indexController from '../index.controller';
|
||||
|
||||
const indexTemplate = require('~features/projects/index.view.html');
|
||||
const projectsListTemplate = require('~features/projects/projectsList.view.html');
|
||||
|
||||
export default {
|
||||
searchPrefix: 'project',
|
||||
name: 'projects',
|
||||
route: '/projects',
|
||||
ncyBreadcrumb: {
|
||||
label: N_('PROJECTS')
|
||||
},
|
||||
data: {
|
||||
activityStream: true,
|
||||
activityStreamTarget: 'project',
|
||||
socket: {
|
||||
groups: {
|
||||
jobs: ['status_changed']
|
||||
}
|
||||
}
|
||||
},
|
||||
params: {
|
||||
project_search: {
|
||||
dynamic: true,
|
||||
}
|
||||
},
|
||||
views: {
|
||||
'@': {
|
||||
templateUrl: indexTemplate,
|
||||
controller: indexController,
|
||||
controllerAs: 'vm'
|
||||
},
|
||||
'projectsList@projects': {
|
||||
templateUrl: projectsListTemplate,
|
||||
controller: projectsListController,
|
||||
controllerAs: 'vm',
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
CredentialTypes: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors',
|
||||
(Rest, $stateParams, GetBasePath, ProcessErrors) => {
|
||||
const path = GetBasePath('credential_types');
|
||||
Rest.setUrl(path);
|
||||
return Rest.get()
|
||||
.then((data) => data.data.results)
|
||||
.catch((response) => {
|
||||
ProcessErrors(null, response.data, response.status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: `Failed to get credential types. GET returned status: ${response.status}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
],
|
||||
ConfigData: ['ConfigService', 'ProcessErrors',
|
||||
function (ConfigService, ProcessErrors) {
|
||||
return ConfigService.getConfig()
|
||||
.then(response => response)
|
||||
.catch(({ data, status }) => {
|
||||
ProcessErrors(null, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: `Failed to get config. GET returned status: status: ${status}`,
|
||||
});
|
||||
});
|
||||
}],
|
||||
Dataset: [
|
||||
'$stateParams',
|
||||
'Wait',
|
||||
'GetBasePath',
|
||||
'QuerySet',
|
||||
($stateParams, Wait, GetBasePath, qs) => {
|
||||
const searchParam = $stateParams.project_search;
|
||||
const searchPath = GetBasePath('projects');
|
||||
|
||||
Wait('start');
|
||||
return qs.search(searchPath, searchParam)
|
||||
.finally(() => Wait('stop'));
|
||||
}
|
||||
],
|
||||
resolvedModels: [
|
||||
'ProjectModel',
|
||||
(Project) => {
|
||||
const models = [
|
||||
new Project(['options']),
|
||||
];
|
||||
return Promise.all(models);
|
||||
},
|
||||
],
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user