Fix designate-dashboard lint

Previously the lint test was failing to run because there was no configuration file for it. This patch adds the .eslintrc file and fixes the found lint issues.
This patch also adds tox environments to run the lint and karma tests.

Change-Id: Idcef4c3ce4e9455acceed645c2530355989a7ee2
This commit is contained in:
Michael Johnson 2022-06-23 21:54:32 +00:00
parent 7ee73c9e1c
commit 64993055e7
29 changed files with 371 additions and 313 deletions

41
.eslintrc Normal file
View File

@ -0,0 +1,41 @@
# Set up globals
globals:
angular: false
extends: openstack
# Most environment options are not explicitly enabled or disabled, only
# included here for completeness' sake. They are commented out, because the
# global updates.py script would otherwise override them during a global
# requirements synchronization.
#
# Individual projects should choose which platforms they deploy to.
env:
# browser global variables.
browser: true
# Adds all of the Jasmine testing global variables for version 1.3 and 2.0.
jasmine: true
# Enable eslint-plugin-angular
plugins:
- angular
# Below we adjust rules specific to horizon's usage of openstack's linting
# rules, and its own plugin inclusions.
rules:
#############################################################################
# Disabled Rules from eslint-config-openstack
#############################################################################
valid-jsdoc: 1
brace-style: 1
no-extra-parens: 1
consistent-return: 1
callback-return: 1
guard-for-in: 1
block-scoped-var: 1
semi-spacing: 1
no-redeclare: 1
no-new: 1
no-warning-comments: 0

View File

@ -71,7 +71,8 @@
'designatedashboard.basePath'
];
function run(registry, basePath) {
function run() {
// function run(registry, basePath) {
//registry.setDefaultSummaryTemplateUrl(basePath + 'table/default-drawer.html');
}

View File

@ -37,12 +37,7 @@
'designatedashboard.resources.os-designate-floatingip.actions.unset'
];
function run(
registry,
resourceTypeString,
setAction,
unsetAction)
{
function run(registry, resourceTypeString, setAction, unsetAction) {
var resourceType = registry.getResourceType(resourceTypeString);
resourceType

View File

@ -33,7 +33,7 @@
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
/*
* @ngDoc factory
* @name designatedashboard.resources.os-designate-floatingip.actions.set
*
@ -51,44 +51,44 @@
var dnsServiceEnabled;
var title = null; // Set once perform is called
var formConfig = {
"schema": {
"type": "object",
"properties": {
"ptrdname": {
"type": "string",
"pattern": /^.+\.$/
schema: {
type: "object",
properties: {
ptrdname: {
type: "string",
pattern: /^.+\.$/
},
"description": {
"type": "string"
},
"ttl": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
description: {
type: "string"
},
ttl: {
type: "integer",
minimum: 0,
maximum: 2147483647
}
}
},
"form": [
form: [
{
"key": "ptrdname",
"title": gettext("Domain Name"),
"description": gettext("Domain name ending in '.'"),
"validationMessage": gettext("Domain must end with '.'"),
"placeholder": "smtp.example.com.",
"type": "text",
"required": true
key: "ptrdname",
title: gettext("Domain Name"),
description: gettext("Domain name ending in '.'"),
validationMessage: gettext("Domain must end with '.'"),
placeholder: "smtp.example.com.",
type: "text",
required: true
},
{
"key": "description",
"type": "textarea",
"title": gettext("Description"),
"description": gettext("Details about the PTR record.")
key: "description",
type: "textarea",
title: gettext("Description"),
description: gettext("Details about the PTR record.")
},
{
"key": "ttl",
"title": gettext("TTL"),
"description": gettext("Time To Live in seconds."),
"type": "number"
key: "ttl",
title: gettext("TTL"),
description: gettext("Time To Live in seconds."),
type: "number"
}
]
};

View File

@ -34,7 +34,7 @@
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
/*
* @ngDoc factory
* @name designatedashboard.resources.os-designate-floatingip.actions.unset
*
@ -50,20 +50,21 @@
schemaFormModalService,
toast,
waitSpinner) {
var dnsServiceEnabled;
var title = null; // Set on perform
var currentFloatingIpId; // Used to remember the ID we are modifying since it isn't returned by the unset API call
// currentFloatingIpId is used to remember the ID we are modifying since
// it isn't returned by the unset API call
var dnsServiceEnabled, currentFloatingIpId;
// Unset it just a simple case of "set", but with ptrdname of 'null'
var formConfig = {
"schema": {
"type": "object",
"properties": {
schema: {
type: "object",
properties: {
}
},
"form": [
form: [
],
"model": {
model: {
}
};
@ -118,7 +119,7 @@
waitSpinner.hideModalSpinner();
}
function onSuccess(response) {
function onSuccess() {
waitSpinner.hideModalSpinner();
toast.add('success', message.success);

View File

@ -26,7 +26,7 @@
'horizon.framework.widgets.toast.service'
];
/**
/*
* @ngdoc service
* @param {Object} httpService
* @param {Object} toastService
@ -60,7 +60,7 @@
* @returns {Object} The result of the API call
*/
function list(params) {
var config = params ? {'params': params} : {};
var config = params ? {params: params} : {};
return httpService.get(apiPassthroughUrl + 'v2/reverse/floatingips', config)
.catch(function () {
toastService.add('error', gettext('Unable to retrieve the floating ip PTRs.'));
@ -68,7 +68,7 @@
}
function get(id, params) {
var config = params ? {'params': params} : {};
var config = params ? {params: params} : {};
return httpService.get(apiPassthroughUrl + 'v2/reverse/floatingips/' + id, config)
.catch(function () {
toastService.add('error', gettext('Unable to get the floating ip PTR ' + id));
@ -94,10 +94,11 @@
description: data.description,
ttl: data.ttl
};
return httpService.patch(apiPassthroughUrl + 'v2/reverse/floatingips/' + floatingIpID, apiData)
return httpService.patch(
apiPassthroughUrl + 'v2/reverse/floatingips/' + floatingIpID, apiData)
.catch(function () {
toastService.add('error', gettext('Unable to set the floating IP PTR record.'));
})
});
}
/**
@ -115,7 +116,7 @@
ptrdname: null,
description: null,
ttl: null
})
});
}
}
}());

View File

@ -1,6 +1,6 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -18,7 +18,9 @@
angular
.module('designatedashboard.resources.os-designate-floatingip.details')
.controller('designatedashboard.resources.os-designate-floatingip.details.overviewController', controller);
.controller(
'designatedashboard.resources.os-designate-floatingip.details.overviewController',
controller);
controller.$inject = [
'designatedashboard.resources.os-designate-floatingip.resourceType',
@ -33,7 +35,7 @@
) {
var ctrl = this;
ctrl.item;
ctrl.item = {};
ctrl.resourceType = registry.getResourceType(resourceTypeCode);
$scope.context.loadPromise.then(onGetResponse);

View File

@ -40,7 +40,8 @@
config.$inject = [ '$provide', '$windowProvider' ];
function config($provide, $windowProvider) {
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/resources/os-designate-floatingip/';
var path = $windowProvider.$get().STATIC_URL +
'designatedashboard/resources/os-designate-floatingip/';
$provide.constant('designatedashboard.resources.os-designate-floatingip.basePath', path);
}
@ -52,13 +53,7 @@
'designatedashboard.resources.util'
];
function run(
detailRoute,
registry,
api,
resourceTypeString,
util)
{
function run(detailRoute, registry, api, resourceTypeString, util) {
var resourceType = registry.getResourceType(resourceTypeString);
resourceType
.setNames(gettext('Floating IP'), gettext('Floating IPs'))
@ -100,12 +95,13 @@
id: 'address',
priority: 1,
sortDefault: true,
template: '<a ng-href="{$ \'' + detailRoute + 'OS::Designate::FloatingIp/\' + item.id $}">{$ item.address $}</a>'
template: '<a ng-href="{$ \'' + detailRoute +
'OS::Designate::FloatingIp/\' + item.id $}">{$ item.address $}</a>'
})
.append({
id: 'ptrdname',
filters: ['noValue'],
priority: 1,
priority: 1
})
.append({
id: 'status',

View File

@ -27,7 +27,7 @@
'designatedashboard.resources.os-designate-recordset.typeMap'
];
/**
/*
* Service to return a schema form config for action forms. Especially useful for forms
* like create and update that differ only in the readonly state of certain form fields.
*
@ -43,7 +43,7 @@
/////////////////
/**
/*
* Returns the create form config
* @returns {{schema, form, model}|*}
*/
@ -51,7 +51,7 @@
return getCreateUpdateFormConfig(false);
}
/**
/*
* Return the update form config
* @returns {{schema, form, model}|*}
*/
@ -59,7 +59,7 @@
return getCreateUpdateFormConfig(true);
}
/**
/*
* Return the create/update form. The two forms are identical except for
* during update, some fields are read-only.
*
@ -68,96 +68,96 @@
*/
function getCreateUpdateFormConfig(readonly) {
return {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": /^.+\.$/
schema: {
type: "object",
properties: {
name: {
type: "string",
pattern: /^.+\.$/
},
"description": {
"type": "string"
description: {
type: "string"
},
"type": {
"type": "string",
"enum": editableTypes
type: {
type: "string",
enum: editableTypes
},
"ttl": {
"type": "integer",
"minimum": 1,
"maximum": 2147483647
ttl: {
type: "integer",
minimum: 1,
maximum: 2147483647
},
"records": {
"type": "array",
"items": {
"type": "object",
"properties": {
"record": {
"type": "string"
records: {
type: "array",
items: {
type: "object",
properties: {
record: {
type: "string"
}
}
},
"minItems": 1,
"uniqueItems": true
minItems: 1,
uniqueItems: true
}
}
},
"form": [
form: [
{
"key": "type",
"readonly": readonly,
"title": gettext("Type"),
"description": gettext("Select the type of record set"),
"type": "select",
"titleMap": editableTypes.map(function toTitleMap(type) {
key: "type",
readonly: readonly,
title: gettext("Type"),
description: gettext("Select the type of record set"),
type: "select",
titleMap: editableTypes.map(function toTitleMap(type) {
return {
"value": type,
"name": typeMap[type]
}
value: type,
name: typeMap[type]
};
}),
"required": true
required: true
},
{
"key": "name",
"readonly": readonly,
"type": "text",
"title": gettext("Name"),
"description": gettext("DNS name for the record set, ending in '.'"),
"validationMessage": gettext("DNS name must end with '.'"),
"placeholder": "www.example.com.",
"required": true
key: "name",
readonly: readonly,
type: "text",
title: gettext("Name"),
description: gettext("DNS name for the record set, ending in '.'"),
validationMessage: gettext("DNS name must end with '.'"),
placeholder: "www.example.com.",
required: true
},
{
"key": "description",
"type": "textarea",
"title": gettext("Description"),
"description": gettext("Details about the zone.")
key: "description",
type: "textarea",
title: gettext("Description"),
description: gettext("Details about the zone.")
},
{
"key": "ttl",
"title": gettext("TTL"),
"description": gettext("Time To Live in seconds."),
"type": "number",
"required": true
key: "ttl",
title: gettext("TTL"),
description: gettext("Time To Live in seconds."),
type: "number",
required: true
},
{
"key": "records",
"title": gettext("Records"),
"type": "array",
"description": gettext("Records for the record set."),
"add": gettext("Add Record"),
"items": [
key: "records",
title: gettext("Records"),
type: "array",
description: gettext("Records for the record set."),
add: gettext("Add Record"),
items: [
{
"key": "records[].record",
"title": gettext("Record")
key: "records[].record",
title: gettext("Record")
}
],
"required": true
required: true
}
],
"model": {
"type": "A",
"ttl": 3600
model: {
type: "A",
ttl: 3600
}
};
}

View File

@ -35,7 +35,7 @@
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
/*
* @ngDoc factory
* @name designatedashboard.resources.os-designate-recordset.actions.create
*
@ -73,7 +73,7 @@
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
}
function allowed(item) {
function allowed() {
return $q.all([
createRecordSetPolicy,
dnsServiceEnabled

View File

@ -1,6 +1,6 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
@ -111,7 +111,7 @@
// Remember the record sets we are allowed to delete so that on delete modal submit
// we can map the recordset ID back to the full recordset. Then we can fetch the
// corresponding zone ID
allowedRecordsets = result.pass.map(getEntity)
allowedRecordsets = result.pass.map(getEntity);
outcome = deleteModal.open(scope, allowedRecordsets, context).then(createResult);
}
return outcome;
@ -157,7 +157,7 @@
function editableRecordType(recordset) {
return $qExtensions.booleanAsPromise(
!(recordset.type == 'NS' && recordset.name == recordset.zone_name) && // not apex NS
!(recordset.type === 'NS' && recordset.name === recordset.zone_name) && // not apex NS
editableTypes.indexOf(recordset.type) > -1
);
}
@ -165,7 +165,7 @@
function deleteRecordSet(recordSetId) {
var recordSet = allowedRecordsets.find(function(element) {
return element.id === recordSetId;
})
});
return recordsetApi.deleteRecordSet(recordSet.zone_id, recordSet.id);
}

View File

@ -37,7 +37,7 @@
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
/*
* @ngDoc factory
* @name designatedashboard.resources.os-designate-recordset.actions.update
*
@ -56,7 +56,7 @@
schemaFormModalService,
toast,
waitSpinner) {
var updateRecordSetPolicy, dnsServiceEnabled;
var updateRecordSetPolicy;
var title = gettext("Update Record Set");
var message = {
success: gettext('Record Set %s was successfully updated.')
@ -93,7 +93,7 @@
function editableRecordType(recordset) {
return $qExtensions.booleanAsPromise(
!(recordset.type == 'NS' && recordset.name == recordset.zone_name) && // not apex NS
!(recordset.type === 'NS' && recordset.name === recordset.zone_name) && // not apex NS
editableTypes.indexOf(recordset.type) > -1
);
}
@ -111,7 +111,7 @@
// Map the records objects to record objects
if (item.hasOwnProperty("records")) {
var records = item.records.map(function (item) {
return {"record": item}
return {record: item};
});
formConfig.model.records = records;
}

View File

@ -27,7 +27,7 @@
'horizon.framework.widgets.toast.service'
];
/**
/*
* @ngdoc service
* @param {Object} httpService
* @param {Object} toastService
@ -48,7 +48,7 @@
///////////////
/**
/*
* @name list
* @description
* Get a list of record sets.
@ -68,7 +68,7 @@
});
}
/**
/*
* @name get
* @description
* Get a single record set by ID.
@ -86,14 +86,15 @@
// common when then delete action removes a record set. Mask this failure by
// always returning a successful promise instead of terminating the $http promise
// in the .error handler.
return httpService.get(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
return httpService.get(
apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
.then(undefined, function onError() {
toastService.add('error', gettext('Unable to retrieve the record set.'));
return $q.when({});
});
}
/**
/*
* @name delete
* @description
* Delete a single record set by ID
@ -106,7 +107,8 @@
* @returns {*}
*/
function deleteRecordSet(zoneId, recordSetId) {
return httpService.delete(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
return httpService.delete(
apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
.catch(function () {
toastService.add('error', gettext('Unable to delete the record set.'));
});
@ -127,7 +129,8 @@
description: data.description,
records: data.records
};
return httpService.put(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId, apiData)
return httpService.put(
apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId, apiData)
.catch(function () {
toastService.add('error', gettext('Unable to update the record set.'));
});

View File

@ -32,7 +32,7 @@
'designatedashboard.resources.os-designate-recordset.resourceType',
'designatedashboard.resources.os-designate-recordset.api',
'designatedashboard.resources.os-designate-recordset.basePath',
'horizon.framework.conf.resource-type-registry.service',
'horizon.framework.conf.resource-type-registry.service'
];
function run(
@ -48,7 +48,7 @@
.setPathParser(pathParser)
.setSummaryTemplateUrl(basePath + 'details/drawer.html');
/**
/*
*
* @param identifier
* The object returned by the pathParser containing the zone ID and record set ID to load
@ -57,11 +57,11 @@
return recordSetApi.get(identifier.zoneId, identifier.recordSetId);
}
/**
/*
* Because a record set is contained by a zone, we implement a custom
* pathGenerator to encode the zone ID and record set ID for the generic
* details panel.
*
*
* @param item
* A record set
*
@ -71,7 +71,7 @@
return item.zone_id + '/' + item.id;
}
/**
/*
* Given a path, extract the zone and record set ids
*
* @param path
@ -86,14 +86,14 @@
return {
zoneId: split[0],
recordSetId: split[1]
}
};
}
resourceType.detailsViews
.prepend({
id: 'recordsetDetailsOverview',
name: gettext('Overview'),
template: basePath + 'details/overview.html',
template: basePath + 'details/overview.html'
}, 0);
// Append a record set view to the zones resource view
@ -102,7 +102,7 @@
.append({
id: 'zoneRecordSets',
name: gettext('Record Sets'),
template: basePath + 'details/zone-recordsets.html',
template: basePath + 'details/zone-recordsets.html'
});
}

View File

@ -1,6 +1,6 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -18,7 +18,9 @@
angular
.module('designatedashboard.resources.os-designate-recordset')
.controller('designatedashboard.resources.os-designate-recordset.zoneRecordSetsController', controller);
.controller(
'designatedashboard.resources.os-designate-recordset.zoneRecordSetsController',
controller);
controller.$inject = [
'$scope',

View File

@ -36,42 +36,43 @@
'OS::Designate::RecordSet')
.constant(
'designatedashboard.resources.os-designate-recordset.typeMap',
{
'A': gettext('A - Address record'),
'AAAA': gettext('AAAA - IPv6 address record'),
'CNAME': gettext('CNAME - Canonical name record'),
'MX': gettext('MX - Mail exchange record'),
'PTR': gettext('PTR - Pointer record'),
'SPF': gettext('SPF - Sender Policy Framework'),
'SRV': gettext('SRV - Service locator'),
'SSHFP': gettext('SSHFP - SSH Public Key Fingerprint'),
'TXT': gettext('TXT - Text record'),
'SOA': gettext('SOA - Start of authority record'),
'NS': gettext('NS - Name server'),
'CAA': gettext('CAA - Certificate Authority Authorization record'),
})
{
A: gettext('A - Address record'),
AAAA: gettext('AAAA - IPv6 address record'),
CNAME: gettext('CNAME - Canonical name record'),
MX: gettext('MX - Mail exchange record'),
PTR: gettext('PTR - Pointer record'),
SPF: gettext('SPF - Sender Policy Framework'),
SRV: gettext('SRV - Service locator'),
SSHFP: gettext('SSHFP - SSH Public Key Fingerprint'),
TXT: gettext('TXT - Text record'),
SOA: gettext('SOA - Start of authority record'),
NS: gettext('NS - Name server'),
CAA: gettext('CAA - Certificate Authority Authorization record')
})
.constant(
'designatedashboard.resources.os-designate-recordset.editableTypes',
[
"A",
"AAAA",
"CNAME",
"MX",
"NS",
"PTR",
"SPF",
"SRV",
"SSHFP",
"TXT",
"CAA",
])
[
"A",
"AAAA",
"CNAME",
"MX",
"NS",
"PTR",
"SPF",
"SRV",
"SSHFP",
"TXT",
"CAA"
])
.config(config)
.run(run);
config.$inject = ['$provide', '$windowProvider'];
function config($provide, $windowProvider) {
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/resources/os-designate-recordset/';
var path = $windowProvider.$get().STATIC_URL +
'designatedashboard/resources/os-designate-recordset/';
$provide.constant('designatedashboard.resources.os-designate-recordset.basePath', path);
}
@ -166,7 +167,9 @@
sortDefault: true,
filters: ['noName'],
// For link format, see pathGenerator in details.module.js
template: '<a ng-href="{$ \'' + detailRoute + 'OS::Designate::RecordSet/\' + item.zone_id + \'/\' + item.id $}">{$ item.name $}</a>'
template: '<a ng-href="{$ \'' + detailRoute +
'OS::Designate::RecordSet/\' + item.zone_id + \'/\' +' +
'item.id $}">{$ item.name $}</a>'
})
.append({
id: 'type',
@ -198,7 +201,7 @@
return {
label: typeMap[key],
key: key
}
};
})
})
.append({
@ -220,7 +223,7 @@
]
});
/**
/*
* list all recordsets within a zone. Requires "zoneId" in the params. All other
* params will be passed unmodified as URL params to the API.
*

View File

@ -41,7 +41,7 @@
/////////////////
/**
/*
* Returns the create zone form config
* @returns {{schema, form, model}|*}
*/
@ -49,7 +49,7 @@
return getCreateUpdateFormConfig(false);
}
/**
/*
* Return the update zone form config
* @returns {{schema, form, model}|*}
*/
@ -57,7 +57,7 @@
return getCreateUpdateFormConfig(true);
}
/**
/*
* Return the create/update zone form. The two forms are identical except for
* during update, some fields are read-only.
*
@ -66,118 +66,118 @@
*/
function getCreateUpdateFormConfig(readonly) {
return {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": /^.+\.$/
schema: {
type: "object",
properties: {
name: {
type: "string",
pattern: /^.+\.$/
},
"description": {
"type": "string"
description: {
type: "string"
},
"email": {
"type": "string",
"format": "email",
"pattern": /^[^@]+@[^@]+$/
email: {
type: "string",
format: "email",
pattern: /^[^@]+@[^@]+$/
},
"type": {
"type": "string",
"enum": [
type: {
type: "string",
enum: [
"PRIMARY",
"SECONDARY"
]
},
"ttl": {
"type": "integer",
"minimum": 1,
"maximum": 2147483647
ttl: {
type: "integer",
minimum: 1,
maximum: 2147483647
},
"masters": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address": {
"type": "string"
masters: {
type: "array",
items: {
type: "object",
properties: {
address: {
type: "string"
}
}
},
"minItems": 1,
"uniqueItems": true
minItems: 1,
uniqueItems: true
}
}
},
"form": [
form: [
{
"key": "name",
"readonly": readonly,
"title": gettext("Name"),
"description": gettext("Zone name ending in '.'"),
"validationMessage": gettext("Zone must end with '.'"),
"placeholder": "example.com.",
"type": "text",
"required": true
key: "name",
readonly: readonly,
title: gettext("Name"),
description: gettext("Zone name ending in '.'"),
validationMessage: gettext("Zone must end with '.'"),
placeholder: "example.com.",
type: "text",
required: true
},
{
"key": "description",
"type": "textarea",
"title": gettext("Description"),
"description": gettext("Details about the zone.")
key: "description",
type: "textarea",
title: gettext("Description"),
description: gettext("Details about the zone.")
},
{
"key": "email",
"title": gettext("Email Address"),
"description": gettext("Email address to contact the zone owner."),
"validationMessage": gettext("Email address must contain a single '@' character"),
"type": "text",
"condition": "model.type == 'PRIMARY'",
"required": true
key: "email",
title: gettext("Email Address"),
description: gettext("Email address to contact the zone owner."),
validationMessage: gettext("Email address must contain a single '@' character"),
type: "text",
condition: "model.type == 'PRIMARY'",
required: true
},
{
"key": "ttl",
"title": gettext("TTL"),
"description": gettext("Time To Live in seconds."),
"type": "number",
"condition": "model.type == 'PRIMARY'",
"required": true
key: "ttl",
title: gettext("TTL"),
description: gettext("Time To Live in seconds."),
type: "number",
condition: "model.type == 'PRIMARY'",
required: true
},
{
"key": "type",
"readonly": readonly,
"title": gettext("Type"),
"description": gettext("Select the type of zone"),
"type": "select",
"titleMap": [
key: "type",
readonly: readonly,
title: gettext("Type"),
description: gettext("Select the type of zone"),
type: "select",
titleMap: [
{
"value": "PRIMARY",
"name": gettext("Primary")
value: "PRIMARY",
name: gettext("Primary")
},
{
"value": "SECONDARY",
"name": gettext("Secondary")
value: "SECONDARY",
name: gettext("Secondary")
}
]
},
{
"key": "masters",
"readonly": readonly,
"title": gettext("Masters"),
"type": "array",
"description": gettext("DNS master(s) for the Secondary zone."),
"condition": "model.type == 'SECONDARY'",
"add": gettext("Add Master"),
"items": [
key: "masters",
readonly: readonly,
title: gettext("Masters"),
type: "array",
description: gettext("DNS master(s) for the Secondary zone."),
condition: "model.type == 'SECONDARY'",
add: gettext("Add Master"),
items: [
{
"key": "masters[].address",
"title": gettext("IP Address")
key: "masters[].address",
title: gettext("IP Address")
}
]
}
],
"model": {
"type": "PRIMARY",
"ttl": 3600
model: {
type: "PRIMARY",
ttl: 3600
}
};
}

View File

@ -34,7 +34,7 @@
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
/*
* @ngDoc factory
* @name designatedashboard.resources.os-designate-zone.actions.create
*

View File

@ -1,6 +1,6 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
@ -70,8 +70,8 @@
//////////////
function initAction() {
context = { };
deleteZonePromise = policy.ifAllowed({rules: [['dns', 'delete_zone']]});
context = { };
deleteZonePromise = policy.ifAllowed({rules: [['dns', 'delete_zone']]});
}
function perform(items, scope) {

View File

@ -35,7 +35,7 @@
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
/*
* @ngDoc factory
* @name designatedashboard.resources.os-designate-zone.actions.update
*
@ -52,7 +52,7 @@
schemaFormModalService,
toast,
waitSpinner) {
var updateZonePolicy, dnsServiceEnabled;
var updateZonePolicy;
var title = gettext("Update Zone");
var message = {
success: gettext('Zone %s was successfully updated.')
@ -98,8 +98,8 @@
// Map the masters objects to address objects
if (item.hasOwnProperty("masters")) {
var masters = item.masters.map(function (item) {
return { "address": item }
})
return { address: item };
});
formConfig.masters = masters;
}
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
@ -112,7 +112,7 @@
if (context.model.hasOwnProperty("masters")) {
var masters = context.model.masters.map(function (item) {
return item.address;
})
});
zoneModel.masters = masters;
}

View File

@ -26,7 +26,7 @@
'horizon.framework.widgets.toast.service'
];
/**
/*
* @ngdoc service
* @param {Object} httpService
* @param {Object} toastService
@ -46,7 +46,7 @@
return service;
///////////////
/**
* @name list
* @description
@ -57,7 +57,7 @@
*
* @param {Object} params
* Query parameters. Optional.
*
*
* @returns {Object} The result of the API call
*/
/*
@ -69,7 +69,7 @@
});
}*/
function list(params) {
var config = params ? {'params': params} : {};
var config = params ? {params: params} : {};
return httpService.get(apiPassthroughUrl + 'v2/zones/', config)
.catch(function () {
toastService.add('error', gettext('Unable to retrieve the zone.'));
@ -93,7 +93,7 @@
});
}
/**
/*
* @name deleteZone
* @description
* Delete a single zone by ID
@ -121,7 +121,7 @@
return httpService.post(apiPassthroughUrl + 'v2/zones/', data)
.catch(function() {
toastService.add('error', gettext('Unable to create the zone.'));
})
});
}
/**
@ -143,10 +143,10 @@
ttl: data.ttl,
description: data.description
};
return httpService.patch(apiPassthroughUrl + 'v2/zones/' + id + '/', apiData )
return httpService.patch(apiPassthroughUrl + 'v2/zones/' + id + '/', apiData)
.catch(function() {
toastService.add('error', gettext('Unable to update the zone.'));
})
});
}
}
}());

View File

@ -50,7 +50,7 @@
.prepend({
id: 'zoneDetailsOverview',
name: gettext('Overview'),
template: basePath + 'details/overview.html',
template: basePath + 'details/overview.html'
}, 0);
function loadFunction(identifier) {

View File

@ -1,6 +1,6 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -33,7 +33,7 @@
) {
var ctrl = this;
ctrl.item;
ctrl.item = {};
ctrl.resourceType = registry.getResourceType(resourceTypeCode);
$scope.context.loadPromise.then(onGetResponse);

View File

@ -40,7 +40,8 @@
config.$inject = ['$provide', '$windowProvider'];
function config($provide, $windowProvider) {
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/resources/os-designate-zone/';
var path = $windowProvider.$get().STATIC_URL +
'designatedashboard/resources/os-designate-zone/';
$provide.constant('designatedashboard.resources.os-designate-zone.basePath', path);
}
@ -136,7 +137,8 @@
id: 'name',
priority: 1,
sortDefault: true,
template: '<a ng-href="{$ \'' + detailRoute + 'OS::Designate::Zone/\' + item.id $}">{$ item.name $}</a>'
template: '<a ng-href="{$ \'' + detailRoute +
'OS::Designate::Zone/\' + item.id $}">{$ item.name $}</a>'
})
.append({
id: 'type',
@ -185,9 +187,9 @@
function typeMap() {
return {
'primary': gettext('Primary'),
'secondary': gettext('Secondary')
}
primary: gettext('Primary'),
secondary: gettext('Secondary')
};
}
function listZones() {

View File

@ -21,10 +21,9 @@
.factory('designatedashboard.resources.util', utilService);
utilService.$inject = [
'horizon.framework.util.q.extensions',
'horizon.framework.util.q.extensions'
];
function utilService($qExtensions) {
var service = {
notDeleted: notDeleted,
@ -47,9 +46,9 @@
return $qExtensions.booleanAsPromise(resource.status !== 'PENDING');
}
/**
* Build a model object based on the given item, using only the fields present in the form config 'key's.
* Only 'truthy' values are copied.
/*
* Build a model object based on the given item, using only the fields
* present in the form config 'key's. Only 'truthy' values are copied.
*
* @param form - an array of objects describing the form. Must have a 'key' attribute.
* @param item - the data to copy into the model
@ -68,19 +67,19 @@
function actionMap() {
return {
'none': gettext('None'),
'create': gettext('Create')
}
none: gettext('None'),
create: gettext('Create')
};
}
function statusMap() {
return {
'active': gettext('Active'),
'pending': gettext('Pending')
}
active: gettext('Active'),
pending: gettext('Pending')
};
}
/**
/*
* hz-resource-table tracks by 'id' which doesn't change when an individual item is updated.
* Create a synthetic '_timestampId' using the item id plus the specified timestamp field.
* When this field is used as a track-by in hz-resource-table, items in the table to update
@ -97,7 +96,7 @@
var _idField = idField || 'id';
var timestamp = Date.now();
items.map(function annotateFloatingIp(item) {
if ( angular.isDefined(timestampField) ) {
if (angular.isDefined(timestampField)) {
timestamp = item[timestampField];
}
item._timestampId = item[_idField] + timestamp;

View File

@ -6,8 +6,9 @@
"repository": "none",
"license": "Apache 2.0",
"devDependencies": {
"eslint": "1.10.3",
"eslint": "^1.10.3",
"eslint-config-openstack": "1.2.4",
"eslint-plugin-angular": "^1.0.1",
"jasmine-core": "2.4.1",
"karma": "~1.1.2",
"karma-firefox-launcher": "2.1.0",
@ -23,4 +24,3 @@
},
"dependencies": {}
}

12
tox.ini
View File

@ -66,3 +66,15 @@ exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,rele
[testenv:releasenotes]
commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
[testenv:eslint]
# npm must be installed on the system, for example
# sudo apt-get install npm
commands = npm install
npm run lint
[testenv:karma]
# npm must be installed on the system, for example
# sudo apt-get install npm
commands = npm install
npm test