mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-08 22:33:24 +00:00
Implement export for 3rd Party sites
This commit is contained in:
@@ -5,7 +5,7 @@ angular.module('app').controller('ExportController', ['$scope', '$stateParams',
|
||||
if ($stateParams.promise) {
|
||||
$scope.export = 'Generating...';
|
||||
$stateParams.promise.then(function(data) {
|
||||
$scope.export = data;
|
||||
$scope.export = (typeof data === 'object') ? angular.toJson(data, true) : data;
|
||||
});
|
||||
} else {
|
||||
$scope.export = angular.toJson($stateParams.data, true);
|
||||
|
||||
@@ -7,7 +7,7 @@ angular.module('app').controller('ImportController', ['$scope', '$stateParams',
|
||||
$scope.ships = Ships;
|
||||
|
||||
$scope.validateJson = function() {
|
||||
var importObj = null;
|
||||
var importObj = null, shipData = null;
|
||||
$scope.jsonValid = false;
|
||||
$scope.errorMsg = null;
|
||||
$scope.builds = null;
|
||||
@@ -22,36 +22,68 @@ angular.module('app').controller('ImportController', ['$scope', '$stateParams',
|
||||
}
|
||||
|
||||
if (typeof importObj != 'object') {
|
||||
$scope.errorMsg = 'Must be an object!';
|
||||
$scope.errorMsg = 'Must be an object or array!';
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!importObj.builds || !Object.keys(importObj.builds).length)) {
|
||||
$scope.errorMsg = 'No builds in data';
|
||||
return;
|
||||
}
|
||||
|
||||
for (var shipId in importObj.builds) {
|
||||
var shipData = Ships[shipId];
|
||||
if (shipData) {
|
||||
for (var buildName in importObj.builds[shipId]) {
|
||||
if (typeof importObj.builds[shipId][buildName] != 'string') {
|
||||
$scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" must be a string!';
|
||||
return;
|
||||
// Using JSON from a simple/shortform/standard export
|
||||
if (importObj.builds && Object.keys(importObj.builds).length) {
|
||||
for (var shipId in importObj.builds) {
|
||||
shipData = Ships[shipId];
|
||||
if (shipData) {
|
||||
for (var buildName in importObj.builds[shipId]) {
|
||||
if (typeof importObj.builds[shipId][buildName] != 'string') {
|
||||
$scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" must be a string!';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Actually build the ship with the code to ensure it's valid
|
||||
Serializer.toShip(new Ship(shipId, shipData.properties, shipData.slots), importObj.builds[shipId][buildName]);
|
||||
} catch (e) {
|
||||
$scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" is not valid!';
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Actually build the ship with the code to ensure it's valid
|
||||
Serializer.toShip(new Ship(shipId, shipData.properties, shipData.slots), importObj.builds[shipId][buildName]);
|
||||
} catch (e) {
|
||||
$scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" is not valid!';
|
||||
} else {
|
||||
$scope.errorMsg = '"' + shipId + '"" is not a valid Ship Id!';
|
||||
return;
|
||||
}
|
||||
$scope.builds = importObj.builds;
|
||||
}
|
||||
|
||||
// Using JSON from a detailed export
|
||||
} else if (importObj.length && importObj[0].references && importObj[0].references.length) {
|
||||
var builds = {};
|
||||
for (var i = 0, l = importObj.length; i < l; i++) {
|
||||
if (typeof importObj[i].name != 'string' || typeof importObj[i].ship != 'string') {
|
||||
$scope.errorMsg = 'Build [' + i + '] must have a ship and build name!';
|
||||
return;
|
||||
}
|
||||
for (var r = 0, rl = importObj[i].references.length; r < rl; r++) {
|
||||
var ref = importObj[i].references[r];
|
||||
if (ref.name == 'Coriolis.io' && ref.code && ref.shipId) {
|
||||
if (!builds[ref.shipId]) {
|
||||
builds[ref.shipId] = {};
|
||||
}
|
||||
try {
|
||||
// Actually build the ship with the code to ensure it's valid
|
||||
shipData = Ships[ref.shipId];
|
||||
Serializer.toShip(new Ship(ref.shipId, shipData.properties, shipData.slots), ref.code);
|
||||
} catch (e) {
|
||||
$scope.errorMsg = importObj[i].ship + ' build "' + importObj[i].name + '" is not valid!';
|
||||
return;
|
||||
}
|
||||
builds[ref.shipId][importObj[i].name] = ref.code;
|
||||
} else {
|
||||
$scope.errorMsg = importObj[i].ship + ' build "' + importObj[i].name + '" has an invalid Coriolis reference!';
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$scope.errorMsg = '"' + shipId + '"" is not a valid Ship Id!';
|
||||
return;
|
||||
}
|
||||
$scope.builds = importObj.builds;
|
||||
$scope.builds = builds;
|
||||
} else {
|
||||
$scope.errorMsg = 'No builds in data';
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.jsonValid = true;
|
||||
|
||||
@@ -219,12 +219,7 @@ angular.module('app').controller('OutfitController', ['$window', '$rootScope', '
|
||||
|
||||
if ($scope.buildName) {
|
||||
$state.go('modal.export', {
|
||||
data: Serializer.toJsonBuild(
|
||||
$scope.buildName,
|
||||
ship,
|
||||
$state.href($state.current.name, $state.params, { absolute: true }),
|
||||
$scope.code || Serializer.fromShip(ship)
|
||||
)
|
||||
data: Serializer.toDetailedBuild($scope.buildName, ship, $scope.code || Serializer.fromShip(ship))
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('app').directive('shipyardHeader', ['lodash', '$rootScope', 'Persist', 'ShipsDB', function(_, $rootScope, Persist, ships) {
|
||||
angular.module('app').directive('shipyardHeader', ['lodash', '$rootScope', '$state', 'Persist', 'Serializer', 'ShipsDB', function(_, $rootScope, $state, Persist, Serializer, ships) {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
@@ -18,17 +18,6 @@ angular.module('app').directive('shipyardHeader', ['lodash', '$rootScope', 'Pers
|
||||
$rootScope.discounts.ship = savedDiscounts[0];
|
||||
$rootScope.discounts.components = savedDiscounts[1];
|
||||
|
||||
// Close menus if a navigation change event occurs
|
||||
$rootScope.$on('$stateChangeStart', function() {
|
||||
scope.openedMenu = null;
|
||||
});
|
||||
|
||||
// Listen to close event to close opened menus or modals
|
||||
$rootScope.$on('close', function() {
|
||||
scope.openedMenu = null;
|
||||
$rootScope.showAbout = false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Save selected insurance option
|
||||
*/
|
||||
@@ -44,6 +33,13 @@ angular.module('app').directive('shipyardHeader', ['lodash', '$rootScope', 'Pers
|
||||
$rootScope.$broadcast('discountChange');
|
||||
};
|
||||
|
||||
scope.detailedExport = function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
scope.openedMenu = null;
|
||||
$state.go('modal.export', { data: Serializer.toDetailedExport(scope.allBuilds) });
|
||||
};
|
||||
|
||||
scope.openMenu = function(e, menu) {
|
||||
e.stopPropagation();
|
||||
if (menu == scope.openedMenu) {
|
||||
@@ -58,16 +54,15 @@ angular.module('app').directive('shipyardHeader', ['lodash', '$rootScope', 'Pers
|
||||
scope.openedMenu = menu;
|
||||
};
|
||||
|
||||
scope.about = function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// Close menus if a navigation change event occurs
|
||||
$rootScope.$on('$stateChangeStart', function() {
|
||||
scope.openedMenu = null;
|
||||
$rootScope.showAbout = true;
|
||||
};
|
||||
});
|
||||
|
||||
$rootScope.hideAbout = function() {
|
||||
$rootScope.showAbout = false;
|
||||
};
|
||||
// Listen to close event to close opened menus or modals
|
||||
$rootScope.$on('close', function() {
|
||||
scope.openedMenu = null;
|
||||
});
|
||||
|
||||
scope.$watchCollection('allBuilds', function() {
|
||||
scope.buildsList = Object.keys(scope.allBuilds).sort();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Service managing seralization and deserialization of models for use in URLs and persistene.
|
||||
*/
|
||||
angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', function(_, GroupMap, MountMap) {
|
||||
angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', 'ShipsDB', 'Ship', '$state', function(_, GroupMap, MountMap, ShipsDB, Ship, $state) {
|
||||
|
||||
/**
|
||||
* Serializes the ships selected components for all slots to a URL friendly string.
|
||||
@@ -66,18 +66,18 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', f
|
||||
);
|
||||
};
|
||||
|
||||
this.toJsonBuild = function(buildName, ship, url, code) {
|
||||
this.toDetailedBuild = function(buildName, ship, code) {
|
||||
var standard = ship.common,
|
||||
hardpoints = ship.hardpoints,
|
||||
internal = ship.internal;
|
||||
|
||||
var data = {
|
||||
$schema: 'http://cdn.coriolis.io/schemas/ship-loadout/1-draft.json#',
|
||||
$schema: 'http://cdn.coriolis.io/schemas/ship-loadout/1.json#',
|
||||
name: buildName,
|
||||
ship: ship.name,
|
||||
references: [{
|
||||
name: 'Coriolis.io',
|
||||
url: url,
|
||||
url: $state.href('outfit', { shipId: ship.id, code: code, bn: buildName }, { absolute: true }),
|
||||
code: code,
|
||||
shipId: ship.id
|
||||
}],
|
||||
@@ -108,6 +108,21 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', f
|
||||
return data;
|
||||
};
|
||||
|
||||
this.toDetailedExport = function(builds) {
|
||||
var data = [];
|
||||
|
||||
for (var shipId in builds) {
|
||||
for (var buildName in builds[shipId]) {
|
||||
var code = builds[shipId][buildName];
|
||||
var shipData = ShipsDB[shipId];
|
||||
var ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
this.toShip(ship, code);
|
||||
data.push(this.toDetailedBuild(buildName, ship, code));
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
this.fromComparison = function(name, builds, facets, predicate, desc) {
|
||||
var shipBuilds = [];
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<ul>
|
||||
Builds & Comparisons
|
||||
<li><a href="#" class="block" ui-sref="modal.export({data: {builds: allBuilds}})">Export</a></li>
|
||||
<li><a href="#" class="block" ng-click="detailedExport($event)">3rd Party Export</a></li>
|
||||
<li><a href="#" class="block" ui-sref="modal.import">Import</a></li>
|
||||
<li><a href="#" class="block" ui-sref="modal.delete">Delete All</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
<button ng-click="stripBuild()">
|
||||
<svg class="icon lg"><use xlink:href="#feather"></use></svg><span class="button-lbl">Low-Weight</span>
|
||||
</button>
|
||||
<!-- <button ng-click="exportBuild($event)" ng-disabled="!buildName">
|
||||
<button ng-click="exportBuild($event)" ng-disabled="!buildName">
|
||||
<svg class="icon lg"><use xlink:href="#download"></use></svg><span class="button-lbl">Export</span>
|
||||
</button> -->
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
218
test/fixtures/anaconda-test-detailed-export.json
vendored
Normal file
218
test/fixtures/anaconda-test-detailed-export.json
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
{
|
||||
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/1.json#",
|
||||
"name": "Test",
|
||||
"ship": "Anaconda",
|
||||
"references": [
|
||||
{
|
||||
"name": "Coriolis.io",
|
||||
"url": "http://localhost:3300/outfit/anaconda/48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4yo5dig%3D.MwBhEYy6duwEziA?bn=Test",
|
||||
"code": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4yo5dig=.MwBhEYy6duwEziA",
|
||||
"shipId": "anaconda"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"standard": {
|
||||
"bulkheads": "Reactive Surface Composite",
|
||||
"powerPlant": {
|
||||
"class": 8,
|
||||
"rating": "A"
|
||||
},
|
||||
"thrusters": {
|
||||
"class": 6,
|
||||
"rating": "A"
|
||||
},
|
||||
"frameShiftDrive": {
|
||||
"class": 6,
|
||||
"rating": "A"
|
||||
},
|
||||
"lifeSupport": {
|
||||
"class": 5,
|
||||
"rating": "A"
|
||||
},
|
||||
"powerDistributor": {
|
||||
"class": 8,
|
||||
"rating": "A"
|
||||
},
|
||||
"sensors": {
|
||||
"class": 8,
|
||||
"rating": "A"
|
||||
},
|
||||
"fuelTank": {
|
||||
"class": 5,
|
||||
"rating": "C"
|
||||
}
|
||||
},
|
||||
"hardpoints": [
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"group": "Plasma Accelerator",
|
||||
"mount": "Fixed"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"group": "Cannon",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"group": "Cannon",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "F",
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "F",
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
}
|
||||
],
|
||||
"utility": [
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "A",
|
||||
"group": "Shield Booster"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "A",
|
||||
"group": "Shield Booster"
|
||||
},
|
||||
null,
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "C",
|
||||
"group": "Kill Warrant Scanner"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "C",
|
||||
"group": "Cargo Scanner"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "F",
|
||||
"group": "Countermeasure",
|
||||
"name": "Electronic Countermeasure"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"group": "Countermeasure",
|
||||
"name": "Chaff Launcher"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"group": "Countermeasure",
|
||||
"name": "Point Defence"
|
||||
}
|
||||
],
|
||||
"internal": [
|
||||
{
|
||||
"class": 7,
|
||||
"rating": "A",
|
||||
"group": "Shield Generator"
|
||||
},
|
||||
{
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"group": "Shield Cell Bank"
|
||||
},
|
||||
{
|
||||
"class": 6,
|
||||
"rating": "E",
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 5,
|
||||
"rating": "D",
|
||||
"group": "Hull Reinforcement Package"
|
||||
},
|
||||
{
|
||||
"class": 5,
|
||||
"rating": "E",
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "E",
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "E",
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"group": "Fuel Scoop"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "A",
|
||||
"group": "FSD Interdictor"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
"class": 3,
|
||||
"hullCost": 141889932,
|
||||
"speed": 180,
|
||||
"boost": 240,
|
||||
"agility": 2,
|
||||
"baseShieldStrength": 350,
|
||||
"baseArmour": 945,
|
||||
"hullMass": 400,
|
||||
"masslock": 23,
|
||||
"shipCostMultiplier": 1,
|
||||
"componentCostMultiplier": 1,
|
||||
"fuelCapacity": 32,
|
||||
"cargoCapacity": 128,
|
||||
"ladenMass": 1339.2,
|
||||
"armourAdded": 240,
|
||||
"shieldMultiplier": 1.4,
|
||||
"totalCost": 882362049,
|
||||
"unladenMass": 1179.2,
|
||||
"armour": 1185,
|
||||
"totalDps": 29,
|
||||
"powerAvailable": 36,
|
||||
"powerRetracted": 23.33,
|
||||
"powerDeployed": 34.96,
|
||||
"unladenRange": 18.49,
|
||||
"fullTankRange": 18.12,
|
||||
"ladenRange": 16.39,
|
||||
"unladenTotalRange": 74.45,
|
||||
"ladenTotalRange": 67.16,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 833
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@ module.exports = function(config) {
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', 'fixture'],
|
||||
preprocessors: {
|
||||
'../build/schemas/**/*.json': ['json_fixtures']
|
||||
'../build/schemas/**/*.json': ['json_fixtures'],
|
||||
'fixtures/**/*.json': ['json_fixtures']
|
||||
},
|
||||
files: [
|
||||
'../build/lib*.js',
|
||||
@@ -11,10 +12,11 @@ module.exports = function(config) {
|
||||
'../node_modules/jsen/dist/jsen.js',
|
||||
'../build/app*.js',
|
||||
'../build/schemas/**/*.json',
|
||||
'fixtures/**/*.json',
|
||||
'tests/**/*.js',
|
||||
],
|
||||
jsonFixturesPreprocessor: {
|
||||
stripPrefix: '.*build',
|
||||
jsonFixturesPreprocessor: {
|
||||
stripPrefix: '.*(/build/)',
|
||||
variableName: '__json__'
|
||||
},
|
||||
reporters: ['mocha'],
|
||||
|
||||
@@ -10,7 +10,6 @@ describe("Serializer Service", function() {
|
||||
|
||||
describe("Detailed Export", function() {
|
||||
var code = '48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4yo5dig=.MwBhEYy6duwEziA',
|
||||
url = 'http://a.test.url.com',
|
||||
anaconda = DB.ships['anaconda'],
|
||||
testBuild,
|
||||
exportData;
|
||||
@@ -18,22 +17,22 @@ describe("Serializer Service", function() {
|
||||
beforeEach(function() {
|
||||
testBuild = new Ship('anaconda', anaconda.properties, anaconda.slots);
|
||||
Serializer.toShip(testBuild, code);
|
||||
exportData = Serializer.toJsonBuild('Test Build', testBuild, url, code);
|
||||
exportData = Serializer.toDetailedBuild('Test', testBuild, code);
|
||||
});
|
||||
|
||||
it("conforms to the ship-loadout schema", function() {
|
||||
var shipLoadoutSchema = __json__['/schemas/ship-loadout/1-draft'];
|
||||
var shipLoadoutSchema = __json__['schemas/ship-loadout/1'];
|
||||
var validate = jsen(shipLoadoutSchema);
|
||||
var valid = validate(exportData);
|
||||
expect(valid).toBeTruthy();
|
||||
});
|
||||
|
||||
xit("contains the correct components", function() {
|
||||
// TODO: implement
|
||||
});
|
||||
|
||||
xit("contains the correct stats", function() {
|
||||
// TODO: implement
|
||||
it("contains the correct components and stats", function() {
|
||||
var anacondaTestExport = __json__['fixtures/anaconda-test-detailed-export'];
|
||||
expect(exportData.components).toEqual(anacondaTestExport.components);
|
||||
expect(exportData.stats).toEqual(anacondaTestExport.stats);
|
||||
expect(exportData.ship).toEqual(anacondaTestExport.ship);
|
||||
expect(exportData.name).toEqual(anacondaTestExport.name);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user