').addClass("center marg-top-15").text(key))
this.container.find("#api-key-popin-frame").empty().append(panel)
},
remove : function(id, row, trigger, container) {
var b = PeeringDB.confirm(gettext("Remove") + " " +row.data("edit-label"), "remove"); ///
var me = this;
$(this.target).on("success", function(ev, data) {
if(b)
me.listing_remove(id, row, trigger, container);
});
if(b) {
this.target.data = { prefix : id, org_id : this.org_id() };
this.target.execute("delete");
} else {
$(this.target).trigger("success", [gettext("Canceled")]); ///
}
},
execute_add : function(trigger, container) {
this.components.add.editable("export", this.target.data);
var data = this.target.data;
this.target.execute("add", this.components.add, function(response) {
if(response.readonly)
response.name = response.name + " (read-only)";
var row = this.add(data.entity, trigger, container, response);
console.log(data)
console.log(row)
this.api_key_popin(response.key)
}.bind(this));
},
add : function(rowId, trigger, container, data) {
var row = this.listing_add(data.prefix, trigger, container, data);
row.attr("data-edit-label", data.prefix + " - " + data.name)
row.data("edit-label", data.prefix + " - " + data.name)
var update_key_form = row.find(".update-key")
update_key_form.find(".popin, .loading-shim").detach()
update_key_form.editable()
return row
},
execute_update : function(trigger, container) {
var row = this.row(trigger);
row.editable("export", this.target.data);
var data = this.target.data;
var id = data.prefix = row.data("edit-id")
console.log(this.target, row)
this.target.execute("update", trigger, function(response) {
}.bind(this));
},
execute_revoke : function(trigger, container) {
var row = this.row(trigger);
var b = PeeringDB.confirm(gettext("Revoke key") + " " +row.data("edit-label"), "remove");
if(!b) {
container.editable("loading-shim", "hide")
return
}
this.components.add.editable("export", this.target.data);
var data = this.target.data;
var id = data.prefix = row.data("edit-id")
this.target.execute("revoke", trigger, function(response) {
this.listing_remove(id, row, trigger, container);
}.bind(this));
}
},
"listing"
);
twentyc.editable.module.register(
"uoar_listing",
{
execute_approve : function(trigger, container) {
var row = trigger.closest("[data-edit-id]").first()
var b = PeeringDB.confirm(gettext("Add user") + " " +row.data("edit-label")+ " " + gettext("to Organization?"), "approve"); ///
if(!b)
return;
this.target.data = {id:row.data("edit-id")};
container.editable("export", this.target.data);
this.target.execute("approve", row, function(data) {
row.detach()
var user_listing = $('#org-user-manager').data("edit-module-instance")
row.data("edit-label", data.full_name)
user_listing.add(data.id, row, user_listing.container, data)
});
},
execute_deny : function(trigger, container) {
var row = trigger.closest("[data-edit-id]").first()
var b = PeeringDB.confirm(gettext("Deny") +" "+row.data("edit-label")+"'s " + gettext("request to join the Organization?"), "deny"); ///
if(!b)
return;
this.target.data = {id:row.data("edit-id")};
container.editable("export", this.target.data);
this.target.execute("deny", row, function(data) {
row.detach();
});
}
},
"base"
);
/**
* editable advanced_search endpoint
*/
twentyc.editable.target.register(
"advanced_search",
{
execute : function() {
var i, data = this.data_clean(true);
data.reftag = this.args[1]
for(i in data) {
if(data[i] && data[i].join)
data[i] = data[i].join(",")
}
window.location.replace(
'?'+$.param(data)
);
},
search : function() {
var reftag = this.args[1];
var data = this.data_clean(true);
var me = $(this), mod=this, sender = this.sender, i;
for(i in data) {
if(typeof data[i] == "object" && data[i].join) {
data[i] = data[i].join(",")
}
}
data.limit = this.limit || 250;
data.depth = 1;
//console.log("Advanced Search", data);
sender.find('.results-empty').hide();
sender.find('.results-cutoff').hide();
PeeringDB.advanced_search_result[reftag] = {"param": $.param(data), data : []}
PeeringDB.API.request(
"GET",
reftag,
null,
data,
function(r) {
me.trigger("success", r.data);
var resultNode = sender.find('.results').first()
resultNode.empty();
if(!r.data.length) {
sender.find('.results-empty').show();
} else {
if(r.data.length == data.limit) {
sender.find('.results-cutoff').show();
}
var row, i, d;
for(i in r.data) {
d = r.data[i];
if(typeof mod["finalize_data_"+reftag] == "function") {
mod["finalize_data_"+reftag](d);
}
row = twentyc.editable.templates.copy("advanced-search-"+reftag+"-item")
if(d.sponsorship) {
$('
').
attr("href", "/sponsors").
addClass("sponsor "+d.sponsorship).
text(d.sponsorship.toLowerCase()+" sponsor").
insertAfter(row.find('.name'));
}
row.find("[data-edit-name]").each(function(idx) {
var fld = $(this);
var value = d[fld.data("edit-name")]
var sortValue = value;
// if field has a sort-target specified get value for sorting
// from there instead
if(fld.data("sort-target")) {
sortValue = d[fld.data("sort-target")];
}
fld.data("sort-value", typeof sortValue == "string" ? sortValue.toLowerCase() : sortValue);
fld.text(value);
if(this.tagName == "A") {
fld.attr("href", fld.attr("href").replace("$id", d.id));
}
});
resultNode.append(row);
}
sender.sortable("sortInitial");
}
PeeringDB.advanced_search_result[reftag].data = r.data
}
).fail(function(response) {
twentyc.editable.target.error_handlers.http_json(response, me, sender);
});
},
finalize_data_net : function(data) {
data.ix_count = data.netixlan_set.length;
data.fac_count = data.netfac_set.length;
data.info_traffic_raw = twentyc.data.get("traffic_speed_by_label")[data.info_traffic] || 0;
data.sponsorship = (twentyc.data.get("sponsors")[data.org_id] || {}).name;
},
finalize_data_ix : function(data) {
data.sponsorship = (twentyc.data.get("sponsors")[data.org_id] || {}).name;
},
finalize_data_fac : function(data) {
data.sponsorship = (twentyc.data.get("sponsors")[data.org_id] || {}).name;
}
},
"base"
);
/**
* editable api endpoint
*/
twentyc.editable.target.register(
"api",
{
execute : function() {
var endpoint = this.args[1]
var requestType = this.args[2]
var method = "POST"
var button = $(this.sender.context);
if(this.context) {
var sender = this.context;
} else {
var sender = this.sender;
}
var me = $(this),
data = this.data,
id = parseInt(this.data._id);
if(requestType == "update") {
if(id)
method = "PUT"
} else if(requestType == "delete") {
method = "DELETE"
} else if(requestType == "create") {
method = "POST"
} else {
throw(gettext("Unknown request type:") + " "+requestType); ///
}
if(button.data("confirm")) {
if(!PeeringDB.confirm(button.data("confirm"))) {
this.sender.editable("loading-shim", "hide")
return;
}
}
PeeringDB.API.request(
method,
endpoint,
id,
data,
function(r) {
if(r)
me.trigger("success", r.data[0]);
else
me.trigger("success", {});
}
).done(function(r) {
if (r.meta && r.meta.geovalidation_warning){
PeeringDB.add_geo_warning(r.meta, endpoint);
} else if (r.meta && r.meta.suggested_address){
PeeringDB.add_suggested_address(r, endpoint);
}
}).fail(function(r) {
if(r.status == 400) {
var k,i,info=[gettext("The server rejected your data")]; ///
for(k in r.responseJSON) {
if(k == "meta") {
var err = r.responseJSON.meta.error;
if(err.indexOf(gettext("not yet been approved")) > 0) { //////
info.push(gettext("Parent entity pending review - please wait for it to be approved before adding entities to it")) ///
} else if(err != "Unknown")
info.push(r.responseJSON.meta.error)
continue;
}
sender.find('[data-edit-name="'+k+'"]').each(function(idx) {
var input = $(this).data("edit-input-instance");
if(input)
input.show_validation_error(r.responseJSON[k]);
});
if(k == "non_field_errors") {
var i;
for(i in r.responseJSON[k])
info.push(r.responseJSON[k][i]);
}
}
me.trigger("error", {
type : "HTTPError",
info : info.join("
")
});
} else {
if(r.responseJSON && r.responseJSON.meta && r.responseJSON.meta.error)
var info = r.responseJSON.meta.error;
else if(r.status == 403)
var info = gettext("You do not have permissions to perform this action")
else
var info = r.status+" "+r.statusText
me.trigger("error", {
type : "HTTPError",
info : info
});
}
});
}
},
"base"
);
/*
* editable api listing module
*/
twentyc.editable.module.register(
"api_listing",
{
loading_shim : true,
init : function() {
this.listing_init();
this.container.on("listing:row-add", function(e, rowId, row, data, me) {
var target = me.target;
if(!target)
target = me.get_target();
var finalizer = "finalize_row_"+target.args[1];
if(me[finalizer]) {
me[finalizer](rowId, row, data);
}
// set sorting and filtering values on new row
row.find('[data-sort-name], [data-filter-name]').each(function(idx) {
var filter = $(this).data('filter-name')
var sort = $(this).data('sort-name')
if(filter)
$(this).attr('data-filter-value', data[filter])
if(sort)
$(this).attr('data-sort-value', data[sort])
});
$(this).find("[data-filter-target]").filterInput("retest");
// always show newly added row
row.show();
row.addClass("status-"+data.status)
PeeringDB.fix_list_offsets()
if(me.components.add)
me.components.add.editable("reset");
});
},
add : function(id, trigger, container, data, context) {
var me =this;
var sentData = data;
this.target.data = data;
this.target.args[2] = "update"
this.target.context = this.components.add || context;
$(this.target).on("success", function(ev, data) {
var finalizer = "finalize_add_"+me.target.args[1];
if(me[finalizer]) {
container.editable("loading-shim","show");
me[finalizer](data, function(data) {
me.listing_add(data.id, trigger, container, data);
container.editable("loading-shim","hide");
}, sentData);
} else {
me.listing_add(data.id, trigger, container, data);
}
});
container.editable("clear-error-popins");
this.target.execute();
},
submit : function(id, data, row, trigger, container) {
data._id = id;
var me = this;
var sentData = data;
this.target.data = data;
this.target.args[2] = "update"
this.target.context = row;
$(this.target).on("success", function(ev, data) {
var finalizer = "finalize_update_"+me.target.args[1];
if(me[finalizer]) {
me[finalizer](id, row, data);
}
});
this.target.execute();
},
remove : function(id, row, trigger, container) {
var b = PeeringDB.confirm(gettext("Remove") + " "+row.data("edit-label"), "remove"); ///
var me = this;
$(this.target).on("success", function(ev, data) {
if(b)
me.listing_remove(id, row, trigger, container);
});
if(b) {
this.target.args[2] = "delete";
this.target.data = { _id : id };
this.target.execute();
} else {
$(this.target).trigger("success", ["Canceled"]);
}
},
// FINALIZERS: IX
finalize_row_ix : function(rowId, row, data) {
// finalize ix row after add
// we need to make sure that the ix name
// is rendered as a link
var ixlnk = $('');
ixlnk.attr("href", "/ix/"+data.id);
ixlnk.text(data.name);
row.find(".name").html(ixlnk);
row.data("edit-label", gettext("Exchange") + ": " +data.name); ///
},
// FINALIZERS: NET
finalize_row_net : function(rowId, row, data) {
// finalize net row after add
// we need to make sure that the network name
// is rendered as a link
var netlnk = $('
');
netlnk.attr("href", "/net/"+data.id);
netlnk.text(data.name);
row.find(".name").html(netlnk);
row.data("edit-label", gettext("Participant") + ": " +data.name); ///
},
// FINALIZERS: FAC
finalize_row_fac : function(rowId, row, data) {
// finalize fac row after add
// we need to make sure that the facility name
// is rendered as a link
var faclnk = $('
');
faclnk.attr("href", "/fac/"+data.id);
faclnk.text(data.name);
row.find(".name").html(faclnk);
row.data("edit-label", gettext("Facility") + ": " +data.name); ///
},
// FINALIZERS: POC
finalize_row_poc : function(rowId, row, data) {
row.editable("payload", {
net_id : data.net_id,
role : data.role
})
//row.find(".phone").val(data.phone);
var phone = row.find(".phone").data("edit-input-instance")
phone.set(data.phone)
row.data("edit-label", gettext("Network Contact") + ": "+data.name); ///
},
finalize_update_poc : function(rowId, row, data) {
row.find(".phone").text(data.phone);
},
// FINALIZERS: NETIX
finalize_row_netixlan : function(rowId, row, data) {
// finalize netix row after add
// we need to make sure that the exchange name
// is rendered as a link and that speed is
// formatted in a humanized way
var ixlnk = $('
');
ixlnk.attr("href", "/ix/"+data.ix.id);
ixlnk.text(data.ix.name);
row.find(".exchange").html(ixlnk);
if(data.operational)
row.addClass("operational")
//row.find(".asn").html(data.asn)
row.find(".speed").data("edit-content-backup", PeeringDB.pretty_speed(data.speed))
row.editable("payload", {
ixlan_id : data.ixlan.id,
net_id : data.net.id
});
// this needs to be fixed in twentyc.edit.js
var rs_peer_html = twentyc.editable.templates.copy("check")
twentyc.editable.input.get("bool").prototype.template_handlers["check"](data.is_rs_peer, rs_peer_html);
row.find(".is_rs_peer").data("edit-content-backup", rs_peer_html)
row.data("edit-label", gettext("Network - Exchange link") + ": "+data.ix.name); ///
},
finalize_add_netixlan : function(data, callback) {
// finalize netix data after add
// we need to get ix name
if(!data.ipaddr4)
data.ipaddr4="";
if(!data.ipaddr6)
data.ipaddr6="";
PeeringDB.API.get("ixlan", data.ixlan_id, function(ixlan) {
data.ixlan = ixlan;
PeeringDB.API.get("ix", ixlan.ix_id, function(ix) {
data.ix = ix;
data.exchange_name = ix.name;
callback(data);
});
});
},
finalize_update_netixlan : function(rowId, row, data) {
var pretty_speed = PeeringDB.pretty_speed(data.speed)
row.find(".speed").data("edit-content-backup", pretty_speed)
row.find(".speed").data("edit-value", data.speed)
row.find(".speed").text(pretty_speed)
if(data.operational)
row.addClass("operational")
else
row.removeClass("operational")
},
// FINALIZERS: NETFAC
finalize_row_netfac : function(rowId, row, data) {
// finalize netfac row after add
// we need to make sure that the facility name
// is rendered as a link
var faclnk = $('
');
faclnk.attr("href", "/fac/"+data.fac_id);
faclnk.text(data.facility);
row.find(".facility").html(faclnk);
row.editable("payload", {
fac_id : data.fac_id,
net_id : data.net_id,
local_asn : data.local_asn
});
row.data("edit-label", gettext("Network - Facility link") + ": "+data.facility); ///
},
finalize_add_netfac : function(data, callback) {
// finalize netfac data after add
// we need to get facility data so we can fill in
// the fields accordingly
PeeringDB.API.get("fac", data.fac_id, function(r) {
data.country = r.country;
data.city = r.city;
data.fac_id = r.id;
data.facility = r.name;
callback(data);
});
},
// FINALIZERS: IXLAN PREFIX
finalize_row_ixpfx : function(rowId, row, data) {
row.editable("payload", {
ixlan_id : data.ixlan_id
})
row.data("edit-label", gettext("IXLAN Prefix") +data.prefix); ///
},
// FINALIZERS: IXFAC
finalize_row_ixfac : function(rowId, row, data) {
// finalize icfac row after add
// we need to make sure that the facility name
// is rendered as a link
var faclnk = $('
');
faclnk.attr("href", "/fac/"+data.fac_id);
faclnk.text(data.facility);
row.find(".facility").html(faclnk);
row.editable("payload", {
fac_id : data.fac_id,
ix_id : data.ix_id,
});
row.data("edit-label", gettext("Exchange - Facility link") + ": "+data.facility); ///
},
finalize_add_ixfac : function(data, callback) {
// finalize ixfac data after add
// we need to get facility data so we can fill in
// the fields accordingly
//
// this is identical to what we need to for netfac, so
// just use that
this.finalize_add_netfac(data, callback);
}
},
"listing"
);
/*
* showdown (markdown) input type
*/
twentyc.editable.input.register(
"markdown",
{
apply : function(value) {
var converter = new showdown.Converter()
if(!value)
value = "";
var html = converter.makeHtml(value.replace(/>/g, '>').replace(/')
},
set : function(value) {
this.element.text(value)
},
get : function(value) {
return this.element.text()
}
},
"text"
);
/*
* mandatory boolean input type
* renders a drop down with 3 choices
*
* - `-`
* - `yes`
* - `no`
*
* Will raise input-required validation error if `-`
* is selected upon form submission
*/
twentyc.editable.input.register(
"mandatory_bool",
{
make : function() {
var node = this.select_make();
this.source.data("edit-required", "yes")
return node;
},
set : function() {
this.load();
},
load : function() {
this.select_load([
{id: "", name: "-"},
{id: "1", name: gettext("Yes")},
{id: "0", name: gettext("No")},
])
}
},
"select"
);
/*
* autocomplete input type
*/
twentyc.editable.input.register(
"autocomplete",
{
confirm_handlers : {},
wire : function() {
var input = this.element;
var url = "/autocomplete/"+this.source.data("edit-autocomplete")
input.yourlabsAutocomplete(
{
url : "/autocomplete/"+
this.source.data("edit-autocomplete"),
minimumCharacters : 2,
choiceSelector : "span",
inputClick : function(e) { return ; }
}
).input.bind("selectChoice", function(a,b) {
input.data("value" , b.data("value"));
input.val(b.text());
input.removeClass("invalid");
input.addClass("valid");
this.render_confirm(b.data("value"));
}.bind(this));
// turn off auto-complete firefox workaround
if(/Firefox/i.test(navigator.userAgent)) {
$(window).off('scroll', $.proxy(this.hide, this))
}
if(this.source.data("edit-autocomplete-text") && this.source.data("edit-value")) {
input.val(this.source.data("edit-autocomplete-text"));
input.data("edit-value", this.source.data("edit-value"));
input.data("value", this.source.data("edit-value"));
}
},
reset_confirm : function() { this.confirm_node().empty(); },
render_confirm : function(id) {
var hdl;
if(hdl=this.confirm_handlers[this.source.data("edit-autocomplete")])
hdl.apply(this, [id])
},
confirm_node : function() {
return this.source.siblings("[data-autocomplete-confirm]")
},
reset : function(resetValue) {
twentyc.editable.input.get("base").prototype.reset.call(this, resetValue);
this.element.data("value","")
this.reset_confirm();
},
get : function() {
var val = this.element.data("value");
if(val === 0 || val === "") {
if(this.source.data("edit-autocomplete-allow-nonexistent")) {
val = this.element.val();
}
}
return val;
},
set : function(value) {
if(value && value.split)
var t = value.split(";");
else
var t = []
this.element.data("value", t[0]);
this.element.val(t[1]);
},
validate : function() {
if(!this.source.data("edit-autocomplete-allow-nonexistent")) {
if(this.get())
return this.get() > 0;
}
return true;
}
},
"string"
);
twentyc.editable.input.get("autocomplete").prototype.confirm_handlers.fac = function(id) {
PeeringDB.API.get("fac", id, function(data) {
this.confirm_node().html(
[
$('
').text(data.address1),
$('
').text(data.address2),
$('
').text(data.city+", "+data.state+", "+data.zipcode),
$('
').text(data.country)
]
)
}.bind(this));
}
/*
* network speed input type
*/
twentyc.editable.input.register(
"network_speed",
{
apply : function(value) {
this.source.html(PeeringDB.pretty_speed(this.get()));
},
export : function() {
console.log("exporting")
return this.convert(this.get())
},
convert : function(value) {
if ( $.isNumeric(value) ){
return value
} else {
return this.reverse_pretty_speed(value)
}
},
validate : function() {
console.log("validating")
// Check if it's an integer
let value = this.element.val();
let suffix = value.slice(-1);
if ( $.isNumeric(value) ){
return true
} else if ( $.isNumeric(value.slice(0,-1) ) && this.validate_suffix(suffix)) {
return true
}
return false
},
validation_message : function() {
return gettext("Needs to be an integer or a speed ending in M, G, or T") ///
},
validate_suffix: function(suffix) {
return ( suffix.toLowerCase() === "m" ||
suffix.toLowerCase() === "g" ||
suffix.toLowerCase() === "t" )
},
reverse_pretty_speed : function(value) {
// Given a pretty speed (string), output the integer speed
const conversion_factor = {
"m": 1,
"g": 1000,
"t": 1000000,
}
const num = parseFloat(value.slice(0, -1));
const unit = value.slice(-1).toLowerCase();
const multiplier = conversion_factor[unit]
// Always return the speed as an integer
return Math.round(num * multiplier)
},
},
"string"
);
/*
* set up input templates
*/
twentyc.editable.templates.register("check", $('
![]()
'));
twentyc.editable.templates.register("poc_email", $('
'));
/*
* set up input template handlers
*/
twentyc.editable.input.get("bool").prototype.template_handlers["check"] = function(value, node, input) {
if(input)
node.attr("src", STATIC_URL+"checkmark"+(input.get()?"":"-off")+".png");
else
node.attr("src", STATIC_URL+"checkmark"+(value?"":"-off")+".png");
}
twentyc.editable.input.get("string").prototype.template_handlers["poc_email"] = function(value, node, input) {
var email = input.source.next().data("edit-input-instance").get()
if(email) {
node.attr("href", "mailto:"+email)
} else {
node.addClass("empty")
}
node.text(input.get());
}
/*
* set up data loaders
*/
twentyc.data.loaders.register(
"data",
{
data : function(id, config) {
config.url = "/data/"+id;
this.XHRGet(id, config);
}
},
"XHRGet" ///
);
twentyc.data.loaders.register(
"org_admin",
{
"org_admin" : function(id, config) {
config.url = "/org_admin/"+id;
config.data = {org_id:this.orgId};
this.XHRGet(id, config);
}
},
"XHRGet" ///
);
twentyc.data.loaders.register(
"network_data",
{
"network_data" : function(id, config) {
config.url = "/data/"+id
config.data = {id:this.id};
this.XHRGet(id, config);
}
},
"XHRGet" ///
);
$.urlParam = function(name){
var results = new RegExp('[\?&]' + name + '=([^]*)').exec(window.location.href);
if(!results)
return 0;
return results[1] || 0;
}
twentyc.data.loaders.assign("locales", "data");
twentyc.data.loaders.assign("countries", "data");
twentyc.data.loaders.assign("countries_b", "data");
twentyc.data.loaders.assign("facilities", "data");
twentyc.data.loaders.assign("sponsors", "data");
twentyc.data.loaders.assign("enum/regions", "data");
twentyc.data.loaders.assign("enum/org_groups", "data");
twentyc.data.loaders.assign("enum/media", "data");
twentyc.data.loaders.assign("enum/net_types", "data");
twentyc.data.loaders.assign("enum/net_types_trunc", "data");
twentyc.data.loaders.assign("enum/net_types_advs", "data");
twentyc.data.loaders.assign("enum/ratios", "data");
twentyc.data.loaders.assign("enum/ratios_trunc", "data");
twentyc.data.loaders.assign("enum/ratios_advs", "data");
twentyc.data.loaders.assign("enum/traffic", "data");
twentyc.data.loaders.assign("enum/scopes", "data");
twentyc.data.loaders.assign("enum/scopes_trunc", "data");
twentyc.data.loaders.assign("enum/scopes_advs", "data");
twentyc.data.loaders.assign("enum/protocols", "data");
twentyc.data.loaders.assign("enum/poc_roles", "data");
twentyc.data.loaders.assign("enum/policy_general", "data");
twentyc.data.loaders.assign("enum/policy_locations", "data");
twentyc.data.loaders.assign("enum/policy_contracts", "data");
twentyc.data.loaders.assign("enum/visibility", "data");
twentyc.data.loaders.assign("enum/bool_choice_str", "data");
$(twentyc.data).on("load-enum/traffic", function(e, payload) {
var r = {}, i = 0, data=payload.data;
for(i=0; i