Compare commits
10 Commits
Author | SHA1 | Date |
---|---|---|
Daniel Asher Resnick | ffd5dc4d77 | 2 years ago |
Daniel Asher Resnick | e6d89e11a7 | 2 years ago |
Daniel Asher Resnick | d740e9a96a | 2 years ago |
Daniel Asher Resnick | 4e570a2ba2 | 2 years ago |
Daniel Asher Resnick | a6ce5d9635 | 2 years ago |
Daniel Asher Resnick | 458721c55b | 2 years ago |
Daniel Asher Resnick | 962f5fff48 | 2 years ago |
Daniel Asher Resnick | 050c71e872 | 2 years ago |
Daniel Asher Resnick | 0df9eb8bca | 2 years ago |
Daniel Asher Resnick | 06f581fb78 | 2 years ago |
@ -0,0 +1,67 @@ |
|||||||
|
a.panel-title:link,.panel-title a:link { text-decoration: none; } |
||||||
|
a.panel-title:visited,.panel-title a:visited { text-decoration: none; } |
||||||
|
a.panel-title:hover,.panel-title a:hover { text-decoration: underline; } |
||||||
|
a.panel-title:active,.panel-title a:active { text-decoration: underline; } |
||||||
|
|
||||||
|
input.editable-name { |
||||||
|
color: #333; |
||||||
|
display: inline; |
||||||
|
width: 12em; |
||||||
|
} |
||||||
|
input.editable-line { |
||||||
|
color: #333; |
||||||
|
} |
||||||
|
input.editable-num { |
||||||
|
color: #333; |
||||||
|
display: inline; |
||||||
|
width: 3em; |
||||||
|
} |
||||||
|
input.editable-name.not-editing { |
||||||
|
background: #F5F5F5; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
input.editable-line.not-editing { |
||||||
|
background: #F5F5F5; |
||||||
|
} |
||||||
|
input.editable-num.not-editing { |
||||||
|
background: #F5F5F5; |
||||||
|
} |
||||||
|
|
||||||
|
.add-skills-traits-container { |
||||||
|
margin-top: 1em; |
||||||
|
margin-bottom: 1em; |
||||||
|
} |
||||||
|
|
||||||
|
.horizontal-input-pair { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 0.5em; |
||||||
|
} |
||||||
|
.horizontal-input-pair label { |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
.horizontal-input-pair input { |
||||||
|
flex-grow: 1; |
||||||
|
} |
||||||
|
div.skill-even { |
||||||
|
} |
||||||
|
div.skill-odd { |
||||||
|
background: #F5F5F5; |
||||||
|
} |
||||||
|
tr.trait-even { |
||||||
|
background: lightgray; |
||||||
|
} |
||||||
|
tr.trait-odd { |
||||||
|
background: #F5F5F5; |
||||||
|
} |
||||||
|
textarea.trait-desc { |
||||||
|
height: 5em; |
||||||
|
width: 98%; |
||||||
|
margin: 1em; |
||||||
|
} |
||||||
|
table.traits{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
table.traits input.editable-name { |
||||||
|
width: 100%; |
||||||
|
} |
@ -0,0 +1,388 @@ |
|||||||
|
// class TimeLogger {
|
||||||
|
// constructor() {
|
||||||
|
// this.logs = [];
|
||||||
|
// this.unlabelled_id = 0;
|
||||||
|
// this.start = this.previous = Date.now();
|
||||||
|
// this.log('start');
|
||||||
|
// }
|
||||||
|
// log(label) {
|
||||||
|
// var now = Date.now();
|
||||||
|
// var log = {
|
||||||
|
// 'when': now,
|
||||||
|
// 'label': label,
|
||||||
|
// 'elapsed': now - this.previous,
|
||||||
|
// 'total': now - this.start
|
||||||
|
// };
|
||||||
|
// this.logs.push(log);
|
||||||
|
// this.previous = now;
|
||||||
|
// return log;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const timelogger = new TimeLogger;
|
||||||
|
// console.log(timelogger.logs[0]);
|
||||||
|
//
|
||||||
|
// console.log(timelogger.log("post-data"));
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
|
||||||
|
function StockedSetting(name, charredSettingData) { |
||||||
|
this.isSubsetting = false; |
||||||
|
if(result = name.match(/(.*) setting/i)) { |
||||||
|
this.name = result[1]; |
||||||
|
} else if(result = name.match(/(.*) subsetting/i)) { |
||||||
|
this.name = result[1]; |
||||||
|
this.isSubsetting = true; |
||||||
|
} else { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
this.lifepaths = []; |
||||||
|
for (let name in charredSettingData) { |
||||||
|
this.lifepaths.push(new StockedLifePath(name, charredSettingData[name])); |
||||||
|
} |
||||||
|
} |
||||||
|
StockedSetting.prototype.addLifepath = function() { |
||||||
|
this.lifepaths.push(new StockedLifePath(this.newLifepathName, {})); |
||||||
|
this.newLifepathName = ""; |
||||||
|
} |
||||||
|
StockedSetting.prototype.removeLifepath = function(index) { |
||||||
|
this.lifepaths.splice(index, 1); |
||||||
|
} |
||||||
|
StockedSetting.prototype.toCharred = function() { |
||||||
|
// let name = this.name + (this.isSubsetting ? " Subsetting" : " Setting";
|
||||||
|
|
||||||
|
let charred = {}; |
||||||
|
for(let lp of this.lifepaths) { |
||||||
|
charred[lp.name] = lp.toCharred(); |
||||||
|
} |
||||||
|
// common traits
|
||||||
|
// stride
|
||||||
|
return charred; |
||||||
|
} |
||||||
|
|
||||||
|
function StockedLifePath(name, charredPathData) { |
||||||
|
if(charredPathData) { |
||||||
|
this.name = name; |
||||||
|
this.time = charredPathData.time; |
||||||
|
this.res = charredPathData.res; |
||||||
|
this.requires = charredPathData.requires; |
||||||
|
this.restrict = charredPathData.restrict; |
||||||
|
this.stat = new StockedLifePathStats(charredPathData.stat); |
||||||
|
this.skills = new StockedLifePathSkills(charredPathData.skills); |
||||||
|
this.traits = new StockedLifePathTraits(charredPathData.traits); |
||||||
|
} else { |
||||||
|
this.stat = new StockedLifePathStats(); |
||||||
|
this.skills = new StockedLifePathSkills(); |
||||||
|
this.traits = new StockedLifePathTraits(); |
||||||
|
} |
||||||
|
|
||||||
|
this.leads_dict = {}; |
||||||
|
if(charredPathData.leads) { |
||||||
|
for(let lead of charredPathData.leads) { this.leads_dict[lead] = true; } |
||||||
|
} |
||||||
|
this.leads = () => Object.keys(this.leads_dict).filter(l => this.leads_dict[l]); |
||||||
|
} |
||||||
|
StockedLifePath.prototype.toCharred = function() { |
||||||
|
let charred = {}; |
||||||
|
charred.time = this.time; |
||||||
|
charred.res = this.res; |
||||||
|
charred.requires = this.requires; |
||||||
|
charred.restrict = this.restrict; |
||||||
|
charred.stat = this.stat.toCharred(); |
||||||
|
charred.skills = this.skills.toCharred(); |
||||||
|
charred.traits = this.traits.toCharred(); |
||||||
|
charred.leads = this.leads(); |
||||||
|
return charred; |
||||||
|
} |
||||||
|
|
||||||
|
function StockedLifePathStats(charredStatData) { |
||||||
|
this.P = 0; |
||||||
|
this.M = 0; |
||||||
|
this.PM = 0; |
||||||
|
if(charredStatData) { |
||||||
|
for (let stat of charredStatData) { |
||||||
|
if(stat[1].toUpperCase() == 'P') { |
||||||
|
this.P += stat[0]; |
||||||
|
} |
||||||
|
else if(stat[1].toUpperCase() == 'M') { |
||||||
|
this.M += stat[0]; |
||||||
|
} |
||||||
|
else if(stat[1].toUpperCase() == 'PM' || stat[0].toUpperCase() == 'MP') { |
||||||
|
this.PM += stat[0]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
StockedLifePathStats.prototype.toString = function() { |
||||||
|
let strs = []; |
||||||
|
if (this.P) { strs.push("+" + this.P + "P"); } |
||||||
|
if (this.M) { strs.push("+" + this.M + "M"); } |
||||||
|
if (this.PM) { strs.push("+" + this.PM + "P/M"); } |
||||||
|
return strs.join(","); |
||||||
|
}; |
||||||
|
StockedLifePathStats.prototype.toCharred = function() { |
||||||
|
let charred = []; |
||||||
|
if(this.P > 0) charred.push([this.P, "p"]); |
||||||
|
if(this.M > 0) charred.push([this.M, "m"]); |
||||||
|
if(this.PM > 0) charred.push([this.PM, "pm"]); |
||||||
|
return charred; |
||||||
|
} |
||||||
|
|
||||||
|
function StockedLifePathSkills(charredLpSkillData) { |
||||||
|
this.lpPoints = 0; |
||||||
|
this.generalPoints = 0; |
||||||
|
this.lpSkills = []; |
||||||
|
if (charredLpSkillData) { |
||||||
|
for (let skill of charredLpSkillData) { |
||||||
|
if(skill.length == 1) { |
||||||
|
this.lpPoints = skill[0]; |
||||||
|
} |
||||||
|
if(skill.length >= 2) { |
||||||
|
if(skill[1].toLowerCase() == "general") { |
||||||
|
this.generalPoints += skill[0]; |
||||||
|
} else { |
||||||
|
this.lpPoints += skill[0]; |
||||||
|
this.lpSkills = this.lpSkills.concat(skill.slice(1)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
StockedLifePathSkills.prototype.removeSkill = function(index) { |
||||||
|
this.lpSkills.splice(index, 1); |
||||||
|
} |
||||||
|
StockedLifePathSkills.prototype.addSkill = function(skill) { |
||||||
|
this.lpSkills.push(skill); |
||||||
|
} |
||||||
|
StockedLifePathSkills.prototype.toString = function() { |
||||||
|
let strs = []; |
||||||
|
if (this.lpPoints) { strs.push(StockedUtil.pts(this.lpPoints, this.lpSkills)); } |
||||||
|
if (this.generalPoints) { strs.push(StockedUtil.pts(this.generalPoints, ["General"])); } |
||||||
|
return strs.join("; "); |
||||||
|
}; |
||||||
|
StockedLifePathSkills.prototype.toCharred = function() { |
||||||
|
let charred = []; |
||||||
|
if(this.lpSkills.length > 0 || this.lpPoints > 0){ |
||||||
|
charred.push([this.lpPoints].concat(this.lpSkills)); |
||||||
|
} |
||||||
|
if(this.generalPoints > 0) |
||||||
|
charred.push([this.generalPoints, "General"]); |
||||||
|
return charred; |
||||||
|
} |
||||||
|
|
||||||
|
function StockedLifePathTraits(charredTraitData) { |
||||||
|
this.lpTraits = []; |
||||||
|
if(charredTraitData) { |
||||||
|
this.points = charredTraitData[0]; |
||||||
|
this.lpTraits = charredTraitData.slice(1); |
||||||
|
} |
||||||
|
} |
||||||
|
StockedLifePathTraits.prototype.removeTrait = function(index) { |
||||||
|
this.lpTraits.splice(index, 1); |
||||||
|
} |
||||||
|
StockedLifePathTraits.prototype.addTrait = function(skill) { |
||||||
|
this.lpTraits.push(skill); |
||||||
|
} |
||||||
|
StockedLifePathTraits.prototype.toString = function() { |
||||||
|
return StockedUtil.pts(this.points, this.lpTraits); |
||||||
|
} |
||||||
|
StockedLifePathTraits.prototype.toCharred = function() { |
||||||
|
return [this.points].concat(this.lpTraits); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Skills
|
||||||
|
|
||||||
|
function StockedSkill(name, charredSkillData) { |
||||||
|
this.name = name; |
||||||
|
this.magic = charredSkillData.magic ? true : false; |
||||||
|
this.roots = { |
||||||
|
Perception: false, |
||||||
|
Will: false, |
||||||
|
Forte: false, |
||||||
|
Power: false, |
||||||
|
Agility: false, |
||||||
|
Speed: false, |
||||||
|
}; |
||||||
|
if(charredSkillData.roots){ |
||||||
|
charredSkillData.roots.map(rootName => this.roots[rootName] = true); |
||||||
|
} |
||||||
|
this.stockSpecific = "TODO"; |
||||||
|
} |
||||||
|
|
||||||
|
// Traits
|
||||||
|
|
||||||
|
function StockedTrait(name, charredTraitData) { |
||||||
|
this.name = name; |
||||||
|
this.cost = charredTraitData.cost; |
||||||
|
this.type = charredTraitData.type; |
||||||
|
this.desc = charredTraitData.desc; |
||||||
|
|
||||||
|
// No logic for these yet
|
||||||
|
this.bonus = charredTraitData.bonus; |
||||||
|
this.restrict = charredTraitData.restrict; |
||||||
|
} |
||||||
|
|
||||||
|
//Ctrl
|
||||||
|
|
||||||
|
var testscope; |
||||||
|
|
||||||
|
function StockedCtrl($scope, $http, burningData) { |
||||||
|
$scope.to_id = function(input) { return input.replaceAll(/\W/g, '_'); }; |
||||||
|
$scope.StockedUtil = StockedUtil; |
||||||
|
|
||||||
|
$scope.TRAIT_TYPES = ["character", "die", "call_on"]; |
||||||
|
|
||||||
|
$scope.settings = []; |
||||||
|
|
||||||
|
/* testing */ |
||||||
|
testscope = $scope; |
||||||
|
$scope.general = { |
||||||
|
'Name': 'Foo', |
||||||
|
'Stride': 7, |
||||||
|
'CommonTraits': [], |
||||||
|
'selectedTrait': '' |
||||||
|
}; |
||||||
|
|
||||||
|
// $scope.parseStock = function (stockData){
|
||||||
|
// let settings = [];
|
||||||
|
// for (let name in stockData) {
|
||||||
|
// settings.push(new StockedSetting(name, stockData[name]));
|
||||||
|
// }
|
||||||
|
// return settings;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// $scope.parseSkills = function (skillsData){
|
||||||
|
// let skills = [];
|
||||||
|
// for (let name in skillsData) {
|
||||||
|
// skills.push(new StockedSkill(name, skillsData[name]));
|
||||||
|
// }
|
||||||
|
// return skills;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// $scope.parseTraits = function (traitsData){
|
||||||
|
// let traits = [];
|
||||||
|
// for (let name in traitsData) {
|
||||||
|
// traits.push(new StockedTrait(name, traitsData[name]));
|
||||||
|
// }
|
||||||
|
// return traits;
|
||||||
|
// };
|
||||||
|
|
||||||
|
/* end testing */ |
||||||
|
|
||||||
|
/* Input/Output */ |
||||||
|
/* end Input/Output */ |
||||||
|
|
||||||
|
$scope.addSetting = function (){ |
||||||
|
this.settings.push(new StockedSetting(this.newSettingName, {})); |
||||||
|
this.newSettingName = ""; |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.removeSetting = function (index) { |
||||||
|
this.settings.splice(index, 1); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.addSkill = function (){ |
||||||
|
this.skills.push(new StockedSkill("New", {})); |
||||||
|
}; |
||||||
|
$scope.removeSkill = function (index) { |
||||||
|
this.skills.splice(index, 1); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.addTrait = function (){ |
||||||
|
this.traits.push(new StockedTrait("New", {})); |
||||||
|
}; |
||||||
|
$scope.removeTrait = function (index) { |
||||||
|
this.traits.splice(index, 1); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.collapseBody = function(data_target, $event) { |
||||||
|
$(data_target).collapse("toggle"); |
||||||
|
if($event) { $event.stopPropagation(); } |
||||||
|
}; |
||||||
|
$scope.editField = function($event, edit) { |
||||||
|
$($event.target).toggleClass("not-editing"); |
||||||
|
}; |
||||||
|
burningData.registerOnAllDatasetsLoaded(function() { |
||||||
|
onLifepathsLoad_Stocked($scope, burningData); |
||||||
|
}); |
||||||
|
|
||||||
|
$scope.editLeads = function($event) { |
||||||
|
let container = $($event.target).closest('.path-leads'); |
||||||
|
container.find(".path-leads-read").toggle(false); |
||||||
|
container.find(".path-leads-write").toggle(true); |
||||||
|
}; |
||||||
|
$scope.readLeads = function($event) { |
||||||
|
let container = $($event.target).closest('.path-leads'); |
||||||
|
container.find(".path-leads-read").toggle(true); |
||||||
|
container.find(".path-leads-write").toggle(false); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.stocked_loadCharredModel = function() { |
||||||
|
file = document.getElementById("stocked_charred_file"); |
||||||
|
file.files[0].text().then((text) => loadCharredModel(this, JSON.parse(text))); |
||||||
|
}; |
||||||
|
$scope.stocked_downLoadCharredModel = function() { |
||||||
|
model = serializeToCharredModel(this); |
||||||
|
$http.post("/stocked_download", model). |
||||||
|
success(function(data,status,headers,config){ |
||||||
|
console.log("huzzah, converting stocked model to charred succeeded. File URL: " + data); |
||||||
|
var frame = document.getElementById("downloadframe"); |
||||||
|
if ( frame ){ |
||||||
|
frame.src = data; |
||||||
|
} |
||||||
|
}). |
||||||
|
error(function(data,status,headers,config){ |
||||||
|
console.log("boo, converting stocked model to charred failed. File URL: " + data); |
||||||
|
$scope.addAlert('tools', "converting stocked model to charred failed: " + data); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Accepts an object, JSON text should be parsed first
|
||||||
|
function loadCharredModel($scope, model) { |
||||||
|
let settings = []; |
||||||
|
for (let name in model) { |
||||||
|
settings.push(new StockedSetting(name, model[name])); |
||||||
|
} |
||||||
|
$scope.settings = settings; |
||||||
|
$scope.$apply(); |
||||||
|
} |
||||||
|
|
||||||
|
function serializeToCharredModel($scope) { |
||||||
|
let model = {}; |
||||||
|
model.settings = {}; |
||||||
|
model.Name = $scope.general.Name; |
||||||
|
$scope.settings.forEach((s) => |
||||||
|
model.settings[s.name + (s.isSubsetting ? " Subsetting" : " Setting")] = s.toCharred()) |
||||||
|
return JSON.stringify(model); |
||||||
|
} |
||||||
|
|
||||||
|
function onLifepathsLoad_Stocked($scope, burningData) { |
||||||
|
// $scope.settings = $scope.parseStock(test_data);
|
||||||
|
// $scope.skills = $scope.parseSkills(test_skills_data);
|
||||||
|
// $scope.traits = $scope.parseTraits(test_traits_data);
|
||||||
|
$scope.charredTraits = Object.keys(burningData.traits); |
||||||
|
$scope.charredSkills = Object.keys(burningData.skills); |
||||||
|
} |
||||||
|
|
||||||
|
var StockedUtil = { |
||||||
|
"pluralize": function(num, thing, withE, nospace) { |
||||||
|
str = ""; |
||||||
|
str += num; |
||||||
|
if (!nospace) { str += ' '; } |
||||||
|
str += thing; |
||||||
|
if(num != 1) { |
||||||
|
if (withE) { str += 'e'; } |
||||||
|
str += 's'; |
||||||
|
} |
||||||
|
return str; |
||||||
|
}, |
||||||
|
"pts": function(num, entries) { |
||||||
|
let str = StockedUtil.pluralize(num, "pt") + ": "; |
||||||
|
if(Array.isArray(entries) && entries.length > 0) { str += entries.join(", "); } |
||||||
|
else { str += "—" } |
||||||
|
return str; |
||||||
|
}//, "filter$properties": (key, value) => (key.startsWith('$') ? undefined : value)
|
||||||
|
|
||||||
|
}; |
@ -0,0 +1,42 @@ |
|||||||
|
function EditableInputController($scope, $element, $attrs) { |
||||||
|
console.log($scope); |
||||||
|
console.log($element); |
||||||
|
var ctrl = this; |
||||||
|
ctrl.isEditing = false; |
||||||
|
|
||||||
|
ctrl.handleModeChange = function() { |
||||||
|
if (ctrl.isEditing) { |
||||||
|
ctrl.onUpdate({value: ctrl.modelValue}); |
||||||
|
ctrl.modelValueCopy = ctrl.modelValue; |
||||||
|
} |
||||||
|
ctrl.isEditing = !ctrl.isEditing; |
||||||
|
}; |
||||||
|
|
||||||
|
ctrl.reset = function() { |
||||||
|
ctrl.modelValue = ctrl.modelValueCopy; |
||||||
|
}; |
||||||
|
|
||||||
|
ctrl.$onInit = function() { |
||||||
|
// Make a copy of the initial value to be able to reset it later
|
||||||
|
ctrl.modelValueCopy = ctrl.modelValue; |
||||||
|
|
||||||
|
// Set a default inputType
|
||||||
|
if (!ctrl.inputType) { |
||||||
|
ctrl.inputType = 'text'; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
export function register(module) { |
||||||
|
console.log(module); |
||||||
|
module.component('editableInput', { |
||||||
|
templateUrl: '/stocked/editableInput_partial', |
||||||
|
controller: EditableInputController, |
||||||
|
bindings: { |
||||||
|
modelValue: '<', |
||||||
|
inputID: '<', |
||||||
|
inputType: '@?', |
||||||
|
onUpdate: '&' |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,23 @@ |
|||||||
|
{ |
||||||
|
"Foo Setting": { |
||||||
|
"Born Foo": { |
||||||
|
"time": 1, |
||||||
|
"res": 5, |
||||||
|
"stat": [ |
||||||
|
[1, "pm"] |
||||||
|
], |
||||||
|
"leads": [ |
||||||
|
"Bar" |
||||||
|
], |
||||||
|
"key_leads": [ |
||||||
|
"Bar Setting" |
||||||
|
], |
||||||
|
"skills": [ |
||||||
|
[3, "General"] |
||||||
|
], |
||||||
|
"traits": [1], |
||||||
|
"common_traits": [] |
||||||
|
} |
||||||
|
}, |
||||||
|
"Bar Setting": {} |
||||||
|
} |
@ -0,0 +1,377 @@ |
|||||||
|
<div class='container' ng-controller='StockedCtrl'> |
||||||
|
<h1 id='intro'>Stocked</h1> |
||||||
|
<div class='well'> |
||||||
|
Stocked (Stock·ed) |
||||||
|
<br> |
||||||
|
<br> |
||||||
|
<ol> |
||||||
|
<li><i>adj.</i> Furnished with more than enough. <i>(ref https://www.vocabulary.com/dictionary/stocked)</i></li> |
||||||
|
<li><i>n.</i> A portmanteau of <i>stock</i> and <i>editor</i>.</li> |
||||||
|
</ol> |
||||||
|
</div> |
||||||
|
<div class='panel panel-default'> |
||||||
|
<div class='panel-heading' > |
||||||
|
<h4 class='panel-title'> |
||||||
|
<a href='' ng-click='collapseBody("#collapse_tools")'>▸</a> |
||||||
|
Tools |
||||||
|
</h4> |
||||||
|
</div> |
||||||
|
<div class='panel-collapse collapse in' id='collapse_tools'> |
||||||
|
<div class='panel-body'> |
||||||
|
<div class='alert alert-danger alert-dismissable' ng-repeat="warn in alertsOfType('tools', 'warn')"> |
||||||
|
<button aria-hidden='true' class='close' ng-click="removeAlert('tools',warn)" type='button'>×</button> |
||||||
|
{{warn}} |
||||||
|
</div> |
||||||
|
<div class='alert alert-success alert-dismissable' ng-repeat="warn in alertsOfType('tools', 'succ')"> |
||||||
|
<button aria-hidden='true' class='close' ng-click="removeAlert('tools',warn)" type='button'>×</button> |
||||||
|
{{warn}} |
||||||
|
</div> |
||||||
|
<div class='container'> |
||||||
|
<div class='row'> |
||||||
|
<div class='col-md-3'> |
||||||
|
<input type="file" id="stocked_charred_file"/> |
||||||
|
<a href='' ng-click='stocked_loadCharredModel()'> |
||||||
|
TODO: Load charred stock model |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<div class='col-md-3'> |
||||||
|
<a href='' ng-click='stocked_downloadCharredModel()'> |
||||||
|
TODO: Download charred stock model |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<div class='col-md-3'> |
||||||
|
<a href='' ng-click='stocked_generateMarkdown()'> |
||||||
|
TODO: Generate Markdown |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='panel-heading'> |
||||||
|
<h4 class='panel-title'> |
||||||
|
<a href='' ng-click='collapseBody("#collapse_general")'>▸</a> |
||||||
|
General |
||||||
|
</h4> |
||||||
|
</div> |
||||||
|
<div class='panel-collapse collapse in' id='collapse_general'> |
||||||
|
<div class='panel-body'> |
||||||
|
<label for='stock-name'>Name:</label> |
||||||
|
<input class='form-control input-lg not-editing editable-name' name='stock-name' id='stock-name' |
||||||
|
ng-model="general.Name" ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
|
||||||
|
<label for='stock-stride'>Stride:</label> |
||||||
|
<input type="number" class='not-editing editable-num' name='stock-stride' id='stock-stride' |
||||||
|
ng-model="general.Stride" ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<br /> |
||||||
|
<div> |
||||||
|
<span>Common traits: {{general.CommonTraits.join(", ")}}</span> |
||||||
|
<select class='form-control' ng-model='general.selectedTrait' ng-options='t for t in charredTraits'></select> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<a href='' ng-click='general.CommonTraits.push(general.selectedTrait)'>Add trait</a> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<a href='' ng-click=''>TODO: Add new trait</a> |
||||||
|
</div> |
||||||
|
<br /> |
||||||
|
TODO: other things in General section? |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='panel-heading'> |
||||||
|
<h4 class='panel-title'> |
||||||
|
<a href='' ng-click='collapseBody("#collapse_settings")'>▸</a> |
||||||
|
Settings |
||||||
|
</h4> |
||||||
|
</div> |
||||||
|
<div class='panel-collapse collapse in' id='collapse_settings'> |
||||||
|
<div class='panel-body'> |
||||||
|
<span class="note-label">Note:</span> |
||||||
|
<span class="note-content"> |
||||||
|
Settings will have " Setting" (or " Subsetting" for subsettings) |
||||||
|
appended to the name in the generated charred model, which is how charred will display them. |
||||||
|
</span> |
||||||
|
<br /> |
||||||
|
|
||||||
|
<a ng-click='collapseBody(".collapse_all_settings", $event)' href=''> |
||||||
|
collapse/expand all settings |
||||||
|
</a> |
||||||
|
<div class='list-group'> |
||||||
|
<div ng-repeat="setting in settings" class='list-group-item'> |
||||||
|
<div class='panel-heading'> |
||||||
|
<a href='' class="panel-title" ng-click='collapseBody("#collapse_" + to_id(setting.name))'>▸</a> |
||||||
|
<input class='form-control input-lg not-editing editable-name' |
||||||
|
ng-model="setting.name" ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<span class="panel-title" style="font-weight: bold;"> |
||||||
|
<input type="checkbox" ng-model="setting.isSubsetting" /> Subsetting? |
||||||
|
</span> |
||||||
|
<a href='' ng-click='removeSetting($index)'>[X]</a> |
||||||
|
</div> |
||||||
|
<div class='panel-collapse collapse in collapse_all_settings' id='collapse_{{to_id(setting.name)}}'> |
||||||
|
<div class='panel-body'> |
||||||
|
<div class="panel"> |
||||||
|
<div class="panel-body"> |
||||||
|
<span class="note-label">Note:</span> |
||||||
|
<span class="note-content"> |
||||||
|
Prefix a lifepath's name with "Born " to have charred consider it a born lifepath; |
||||||
|
i.e. selectable if and only if it is the first lifepath. |
||||||
|
</span> |
||||||
|
<br /> |
||||||
|
|
||||||
|
<a ng-click='collapseBody(".collapse_all_"+to_id(setting.name), $event)' href=''> |
||||||
|
collapse/expand all paths in setting |
||||||
|
</a> |
||||||
|
<div class='container-fluid'> |
||||||
|
<div class='row'> |
||||||
|
<div class='h4 col-md-3'>Lifepath</div> |
||||||
|
<div class='h4 col-md-1'>Time</div> |
||||||
|
<div class='h4 col-md-1'>Res</div> |
||||||
|
<div class='h4 col-md-3'>Stat</div> |
||||||
|
<div class='h4 col-md-4'>Leads</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div ng-repeat="path in setting.lifepaths"> |
||||||
|
<div class='panel-heading'> |
||||||
|
<div class='container-fluid'> |
||||||
|
<div class='row'> |
||||||
|
<div class="col-md-3"> |
||||||
|
<a href='' class="panel-title" ng-click='collapseBody("#collapse_" + to_id(path.name))'>▸</a> |
||||||
|
<input ng-model="path.name" |
||||||
|
class='form-control input-lg not-editing editable-name' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<a href='' ng-click='setting.removeLifepath($index)'>[X]</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="col-md-1"> |
||||||
|
<input type="number" ng-model="path.time" |
||||||
|
class='not-editing editable-num' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<span>yrs</span> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="col-md-1"> |
||||||
|
<input type="number" ng-model="path.res" |
||||||
|
class='not-editing editable-num' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="col-md-3"> |
||||||
|
<label for="{{to_id(path.name)}}_M">M: </label> |
||||||
|
<input type="number" ng-model="path.stat.M" id="{{to_id(path.name)}}_M" |
||||||
|
class='not-editing editable-num' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<label for="{{to_id(path.name)}}_P">P: </label> |
||||||
|
<input type="number" ng-model="path.stat.P" id="{{to_id(path.name)}}_M" |
||||||
|
class='not-editing editable-num' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<label for="{{to_id(path.name)}}_PM">P/M: </label> |
||||||
|
<input type="number" ng-model="path.stat.PM" id="{{to_id(path.name)}}_M" |
||||||
|
class='not-editing editable-num' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class='h5 col-md-4 path-leads'> |
||||||
|
<div class="path-leads-read"> |
||||||
|
<span>Leads: </span><i>{{path.leads().join(", ")}}</i> |
||||||
|
<a href='' ng-click='editLeads($event)'>Edit</a> |
||||||
|
</div> |
||||||
|
<div class="path-leads-write" hidden="hidden"> |
||||||
|
<div ng-repeat="setting in settings"> |
||||||
|
<input type="checkbox" id='{{to_id(path.name)}}-to-{{to_id(setting.name)}}' |
||||||
|
ng-model='path.leads_dict[setting.name]' value='{{to_id(setting.name)}}' /> |
||||||
|
<label for='{{to_id(path.name)}}-to-{{to_id(setting.name)}}'> |
||||||
|
{{setting.name}} |
||||||
|
</label> |
||||||
|
</div> |
||||||
|
<a href='' ng-click='readLeads($event)'>Done</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='panel-collapse collapse in collapse_all_{{to_id(setting.name)}}' id='collapse_{{to_id(path.name)}}'> |
||||||
|
<div class='panel-body'> |
||||||
|
<span ng-if='$first'>TODO: Born/common traits</span> |
||||||
|
|
||||||
|
<div> |
||||||
|
<b><i>Skills:</i></b> |
||||||
|
<span ng-if='path.skills.lpSkills.length > 0' ng-click='editPoints($event)'> |
||||||
|
{{StockedUtil.pluralize(path.skills.lpPoints, "pt")}}: |
||||||
|
</span> |
||||||
|
<div style="display: inline;" ng-repeat='skill in path.skills.lpSkills track by $index'> |
||||||
|
{{skill}}<a href='' ng-click='path.skills.removeSkill($index)'>[X]</a><!-- |
||||||
|
--><span ng-if='!$last'>,</span></div><!-- |
||||||
|
--><span ng-if='path.skills.lpSkills.length > 0 && path.skills.generalPoints > 0'>;</span> |
||||||
|
<span ng-if='path.skills.generalPoints > 0'>{{StockedUtil.pluralize(path.skills.generalPoints, "pt")}}: General</span> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div> |
||||||
|
<b><i>Traits:</i></b> |
||||||
|
<span ng-if='path.traits.lpTraits.length == 0'>—</span> |
||||||
|
<span ng-if='path.traits.lpTraits.length > 0' ng-click='editPoints($event)'> |
||||||
|
{{StockedUtil.pluralize(path.traits.points, "pt")}}: |
||||||
|
</span> |
||||||
|
<div style="display: inline;" ng-repeat='trait in path.traits.lpTraits track by $index'> |
||||||
|
{{trait}}<a href='' ng-click='path.traits.removeTrait($index)'>[X]</a><!-- |
||||||
|
--><span ng-if='!$last'>,</span></div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div ng-if="path.requires" class="horizontal-input-pair"> |
||||||
|
<label for="{{to_id(path.name)}}-requires"><b><i>Requires: </i></b></label> |
||||||
|
<input ng-model="path.requires" id="{{to_id(path.name)}}-requires" |
||||||
|
class='form-control not-editing editable-line' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
</div> |
||||||
|
<div ng-if="path.restrict" class="horizontal-input-pair"> |
||||||
|
<label for="{{to_id(path.name)}}-restrict"><b><i>Restrictions: </i></b></label> |
||||||
|
<input ng-model="path.restrict" id="{{to_id(path.name)}}-restrict" |
||||||
|
class='form-control not-editing editable-line' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="add-skills-traits-container" class="container"> |
||||||
|
<div class='row'> |
||||||
|
<div class='col-md-3'> |
||||||
|
<select class='form-control' ng-model='path.selectedSkill' ng-options='s for s in charredSkills'></select> |
||||||
|
</div> |
||||||
|
<div class='col-md-1'> |
||||||
|
<a href='' ng-click='path.skills.addSkill(path.selectedSkill)'>Add skill</a> |
||||||
|
</div> |
||||||
|
<div class='col-md-2'> |
||||||
|
<a href='' ng-click=''>TODO: Add new skill</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class='col-md-3'> |
||||||
|
<select class='form-control' ng-model='path.selectedTrait' ng-options='t for t in charredTraits'></select> |
||||||
|
</div> |
||||||
|
<div class='col-md-1'> |
||||||
|
<a href='' ng-click='path.traits.addTrait(path.selectedTrait)'>Add trait</a> |
||||||
|
</div> |
||||||
|
<div class='col-md-2'> |
||||||
|
<a href='' ng-click=''>TODO: Add new trait</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<span>WISHLIST: requires expression</span> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='panel panel-default'> |
||||||
|
<input class='form-control input-lg not-editing editable-name' |
||||||
|
name='new-lifepath-name' id='new-lifepath-name' |
||||||
|
ng-model="setting.newLifepathName" ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<a href='' ng-click='setting.addLifepath()'>Add new lifepath</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='panel panel-default'> |
||||||
|
<input class='form-control input-lg not-editing editable-name' |
||||||
|
name='new-setting-name' id='new-setting-name' |
||||||
|
ng-model="newSettingName" ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
<a href='' ng-click='addSetting()'>Add new setting</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='panel-heading'> |
||||||
|
<h4 class='panel-title'> |
||||||
|
<a href='' ng-click='collapseBody("#collapse_skills")'>▸</a> |
||||||
|
Skills |
||||||
|
</h4> |
||||||
|
</div> |
||||||
|
<div class='panel-collapse collapse in' id='collapse_skills'> |
||||||
|
<div class='panel-body'> |
||||||
|
<div class='container-fluid'> |
||||||
|
<div class='row'> |
||||||
|
<div class='h4 col-md-3'>Skill</div> |
||||||
|
<div class='h4 col-md-1'>Sorcerous?</div> |
||||||
|
<div class='h4 col-md-8'>Roots</div> |
||||||
|
<%# <div class='h4 col-md-2'>Stock specific?</div> %> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div ng-repeat='skill in skills' class='row' ng-class-even="'skill-even'" ng-class-odd="'skill-odd'"> |
||||||
|
<div class='h4 col-md-3'> |
||||||
|
<input ng-model="skill.name" |
||||||
|
class='form-control input-lg not-editing editable-name' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
</div> |
||||||
|
<div class='h4 col-md-1'><input type="checkbox" ng-model='skill.magic'></div> |
||||||
|
<div class='h4 col-md-8'> |
||||||
|
<div class="skill-roots-write"> |
||||||
|
<span ng-repeat="(root,is) in skill.roots"> |
||||||
|
<input type="checkbox" id='{{to_id(skill.name)-to_id(root)}}' ng-model='is'/> |
||||||
|
<label for='{{to_id(skill.name)-to_id(root)}}'> {{root}} </label> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='row'> |
||||||
|
<div class='h4 col-md-12'><a href='' ng-click='addSkill()'>Add new skill</a></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class='panel-heading'> |
||||||
|
<h4 class='panel-title'> |
||||||
|
<a href='' ng-click='collapseBody("#collapse_traits")'>▸</a> |
||||||
|
Traits |
||||||
|
</h4> |
||||||
|
</div> |
||||||
|
<div class='panel-collapse collapse in' id='collapse_traits'> |
||||||
|
<div class='panel-body'> |
||||||
|
<table class="traits"> |
||||||
|
<tr> |
||||||
|
<th>Trait</th> |
||||||
|
<th>Cost</th> |
||||||
|
<th>Type</th> |
||||||
|
<%# <div class='h4 col-md-2'>Bonus</div> %> |
||||||
|
<%# <div class='h4 col-md-2'>Restrictions</div> %> |
||||||
|
</tr> |
||||||
|
<%# </div> %> |
||||||
|
<tr ng-repeat-start='trait in traits' ng-class-even="'trait-even'" ng-class-odd="'trait-odd'"> |
||||||
|
<td> |
||||||
|
<input ng-model="trait.name" |
||||||
|
class='form-control input-lg not-editing editable-name' |
||||||
|
ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
</td> |
||||||
|
<td> |
||||||
|
<input type="number" class='not-editing editable-num' |
||||||
|
ng-model="trait.cost" ng-click="$event.stopPropagation()" |
||||||
|
ng-focus='editField($event, true)' ng-blur='editField($event, false)' /> |
||||||
|
</td> |
||||||
|
<td> |
||||||
|
<select class='form-control' ng-model='trait.type' ng-options='t for t in TRAIT_TYPES'></select> |
||||||
|
</td> |
||||||
|
<td><a href='' ng-click='removeTrait($index)'>[X]</a></td> |
||||||
|
</tr> |
||||||
|
<%# <div class='h4 col-md-2'>WISHLIST</div> %> |
||||||
|
<%# <div class='h4 col-md-2'>WISHLIST</div> %> |
||||||
|
<tr ng-repeat-end ng-class-even="'trait-even'" ng-class-odd="'trait-odd'"> |
||||||
|
<td colspan="99"><textarea class='trait-desc' ng-model='trait.desc'></textarea></td> |
||||||
|
</tr> |
||||||
|
</table> |
||||||
|
<div class='row'> |
||||||
|
<div class='h4 col-md-12'><a href='' ng-click='addTrait()'>Add new trait</a></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
@ -0,0 +1,6 @@ |
|||||||
|
<span ng-if='$ctrl.label' for='{{$ctrl.inputID}}'>{{$ctrl.label}}</span> |
||||||
|
<span ng-switch='$ctrl.isEditing'> |
||||||
|
<input ng-switch-when="true" ng-model='$ctrl.modelValue' ng-blur='$ctrl.handleModeChange()' |
||||||
|
id='{{$ctrl.inputID}}' type='{{$ctrl.inputType}}' class="editable-input editing"> |
||||||
|
<span ng-switch-default class="editable-input">{{$ctrl.modelValue}}</span> |
||||||
|
</span> |
Loading…
Reference in new issue