GH-1 Add Cohort functionality

- Closes #1
- Adds cohort functionality and styles
- Adds Cohort block view
- Adds "Add Item" functionality
- CSS design fixes
This commit is contained in:
Peter Varaksin 2020-05-04 13:10:57 +03:00
parent 8a8cb614b6
commit 6a10138291
15 changed files with 561 additions and 212 deletions

View file

@ -35,14 +35,6 @@ export class BladesActorSheet extends ActorSheet {
activateListeners(html) {
super.activateListeners(html);
// // Activate tabs
// let tabs = html.find('.tabs');
// let initial = this._sheetTab;
// new Tabs(tabs, {
// initial: initial,
// callback: clicked => this._sheetTab = clicked.data("tab")
// });
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
@ -65,27 +57,6 @@ export class BladesActorSheet extends ActorSheet {
/** @override */
_updateObject(event, formData) {
// Handle the free-form attributes list
// const formAttrs = expandObject(formData).data.attributes || {};
// const attributes = Object.values(formAttrs).reduce((obj, v) => {
// let k = v["key"].trim();
// if ( /[\s\.]/.test(k) ) return ui.notifications.error("Attribute keys may not contain spaces or periods");
// delete v["key"];
// obj[k] = v;
// return obj;
// }, {});
// // Remove attributes which are no longer used
// for ( let k of Object.keys(this.object.data.data.attributes) ) {
// if ( !attributes.hasOwnProperty(k) ) attributes[`-=${k}`] = null;
// }
// // Re-combine formData
// formData = Object.entries(formData).filter(e => !e[0].startsWith("data.attributes")).reduce((obj, e) => {
// obj[e[0]] = e[1];
// return obj;
// }, {_id: this.object._id, "data.attributes": attributes});
// Update the Actor
return this.object.update(formData);

View file

@ -151,4 +151,21 @@ export class BladesHelpers {
}, obj);
}
/**
* Add item functionality
*/
static _addOwnedItem(event, actor) {
event.preventDefault();
const a = event.currentTarget;
const item_type = a.dataset.itemType;
let data = {
name: randomID(),
type: item_type
};
return actor.createEmbeddedEntity("OwnedItem", data);
}
}

View file

@ -50,7 +50,7 @@ export class BladesCrewSheet extends ActorSheet {
if (!this.options.editable) return;
// Update Inventory Item
html.find('.item-body').click(ev => {
html.find('.item-sheet-open').click(ev => {
const element = $(ev.currentTarget).parents(".item");
const item = this.actor.getOwnedItem(element.data("itemId"));
item.sheet.render(true);
@ -63,6 +63,11 @@ export class BladesCrewSheet extends ActorSheet {
element.slideUp(200, () => this.render(false));
});
// Add a new Cohort
html.find('.add-item').click(ev => {
BladesHelpers._addOwnedItem(ev, this.actor);
});
// Toggle Turf
html.find('.turf-select').click(ev => {
const element = $(ev.currentTarget).parents(".item");
@ -77,6 +82,19 @@ export class BladesCrewSheet extends ActorSheet {
[turf_checkbox_name]: !turf_current_status});
this.render(false);
});
// Cohort Block Harm handler
html.find('.cohort-block-harm input[type="radio"]').change(ev => {
const element = $(ev.currentTarget).parents(".item");
let item_id = element.data("itemId")
let harm_id = $(ev.currentTarget).val();
this.actor.updateEmbeddedEntity('OwnedItem', {
_id: item_id,
"data.harm": [harm_id]});
this.render(false);
});
}
/* -------------------------------------------- */
@ -88,5 +106,19 @@ export class BladesCrewSheet extends ActorSheet {
}
/* -------------------------------------------- */
/* Form Submission */
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
// Update the Item
super._updateObject(event, formData);
if (event.target.name === "data.tier") {
this.render(true);
}
}
/* -------------------------------------------- */
}

View file

@ -31,14 +31,6 @@ export class BladesItemSheet extends ItemSheet {
/* -------------------------------------------- */
/** @override */
getData() {
const data = super.getData();
return data;
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);

View file

@ -3,4 +3,50 @@
* @extends {Item}
*/
export class BladesItem extends Item {
/* override */
prepareData() {
super.prepareData();
const item_data = this.data;
const data = item_data.data;
console.log("prepare item " + item_data.type);
if (item_data.type === "cohort") {
this._prepareCohort(data);
}
}
/**
* Prepares Cohort data
*
* @param {object} data
*/
_prepareCohort(data) {
let quality = 0;
let scale = 0;
// Adds Scale and Quality
if (this.actor) {
switch (data.cohort[0]) {
case "Gang":
scale = parseInt(this.actor.data.data.tier[0]);
quality = parseInt(this.actor.data.data.tier[0]);
break;
case "Expert":
scale = 1;
quality = parseInt(this.actor.data.data.tier[0]) + 1;
break;
}
}
data.scale = scale;
data.quality = quality;
this.data.data = data;
}
}

View file

@ -11,7 +11,8 @@ export const preloadHandlebarsTemplates = async function() {
// Actor Sheet Partials
"systems/blades-in-the-dark/templates/parts/coins.html",
"systems/blades-in-the-dark/templates/parts/attributes.html",
"systems/blades-in-the-dark/templates/parts/turf-list.html"
"systems/blades-in-the-dark/templates/parts/turf-list.html",
"systems/blades-in-the-dark/templates/parts/cohort-block.html"
];
// Load the template parts

View file

@ -71,7 +71,7 @@
width: 5px;
border-radius: 24px;
background-image: none !important;
background-color: red !important;
background-color: $red !important;
margin-right: 0px;
}
}
@ -157,7 +157,7 @@
display: none;
&:checked ~ .checkmark {
color: red;
color: $red;
}
}
@ -238,14 +238,14 @@
width: $turf_width;
height: $turf_height;
background-color: lightgray;
background-color: $lightgray;
position: relative;
margin: $turf_margin;
flex-grow: initial;
&.turf-selected {
.connector {
background-color: gray;
background-color: $gray;
z-index: 1;
}
}
@ -254,7 +254,7 @@
position: absolute;
display: block;
background-color: lightgray;
background-color: $lightgray;
&.right,
&.left {
@ -285,7 +285,7 @@
&.turf-selected {
background-color: gray;
background-color: $gray;
}
.turf-description {

View file

@ -14,6 +14,10 @@ $almost_white: #EEEFFF;
* {
font-family: Georgia, "Bitstream Charter", "Times New Roman", serif;
header {
margin-bottom: 10px;
}
ul {
list-style: none;
}
@ -38,7 +42,7 @@ $almost_white: #EEEFFF;
flex-direction: row;
justify-content: space-between;
> * {
> *:not(.label-stripe) {
margin-right: 10px;
&:last-child {
@ -103,10 +107,26 @@ $almost_white: #EEEFFF;
margin-bottom: 10px;
position: relative;
padding-left: 10px;
padding-right: 10px;
display: flex;
font-weight: bold;
}
.label-stripe-gray {
text-transform: uppercase;
background-color: $gray;
margin-bottom: 10px;
position: relative;
padding-left: 10px;
padding-right: 10px;
display: flex;
font-weight: bold;
}
.description {
font-style: italic;
}
// Stress and Trauma
.big-teeth-section {
@ -440,11 +460,65 @@ $almost_white: #EEEFFF;
}
}
.window-app {
.window-content {
// background: url("https://wallpapertag.com/wallpaper/middle/c/3/6/294219-old-paper-background-1920x1200-for-desktop.jpg") repeat;
// Cohorts styling
.edgeflaw {
input {
display: none;
&:checked {
& + label {
color: $red;
}
}
}
}
#gang-expert-type-selector {
#gang-type-boxes {
flex-wrap: wrap;
}
}
.cohorts {
flex-wrap: wrap;
.cohort-block-wrapper {
width: 400px;
}
.label-stripe {
margin-bottom: 0px;
}
.cohort-body {
> div {
margin-bottom: 10px;
}
}
.cohort-block-harm {
justify-content: space-around;
input[type="radio"] {
display: none;
&:checked + label {
color: $almost_white;
font-weight: bold;
background-color: $almost_black;
}
}
label {
border: 2px solid $almost_black;
border-top: none;
padding: 5px;
}
}
}
}

View file

@ -28,6 +28,9 @@
* {
font-family: Georgia, "Bitstream Charter", "Times New Roman", serif;
}
* header {
margin-bottom: 10px;
}
* ul {
list-style: none;
}
@ -46,10 +49,10 @@
flex-direction: row;
justify-content: space-between;
}
* section > * {
* section > *:not(.label-stripe) {
margin-right: 10px;
}
* section > *:last-child {
* section > *:not(.label-stripe):last-child {
margin-right: 0px;
}
* section .grow-one {
@ -100,9 +103,23 @@
margin-bottom: 10px;
position: relative;
padding-left: 10px;
padding-right: 10px;
display: flex;
font-weight: bold;
}
* .label-stripe-gray {
text-transform: uppercase;
background-color: #999;
margin-bottom: 10px;
position: relative;
padding-left: 10px;
padding-right: 10px;
display: flex;
font-weight: bold;
}
* .description {
font-style: italic;
}
* .big-teeth-section {
border-top: 3px solid #191813;
display: flex;
@ -557,19 +574,19 @@
* #turf-list.section-non-editable .turf-block {
width: 130px;
height: 100px;
background-color: lightgray;
background-color: #CCC;
position: relative;
margin: 20px;
flex-grow: initial;
}
* #turf-list.section-non-editable .turf-block.turf-selected .connector {
background-color: gray;
background-color: #999;
z-index: 1;
}
* #turf-list.section-non-editable .turf-block .connector {
position: absolute;
display: block;
background-color: lightgray;
background-color: #CCC;
}
* #turf-list.section-non-editable .turf-block .connector.right, * #turf-list.section-non-editable .turf-block .connector.left {
width: 40px;
@ -594,7 +611,7 @@
top: 100px;
}
* #turf-list.section-non-editable .turf-block.turf-selected {
background-color: gray;
background-color: #999;
}
* #turf-list.section-non-editable .turf-block .turf-description {
border: none;
@ -622,19 +639,19 @@
* #turf-list.section-editable .turf-block {
width: 130px;
height: 125px;
background-color: lightgray;
background-color: #CCC;
position: relative;
margin: 20px;
flex-grow: initial;
}
* #turf-list.section-editable .turf-block.turf-selected .connector {
background-color: gray;
background-color: #999;
z-index: 1;
}
* #turf-list.section-editable .turf-block .connector {
position: absolute;
display: block;
background-color: lightgray;
background-color: #CCC;
}
* #turf-list.section-editable .turf-block .connector.right, * #turf-list.section-editable .turf-block .connector.left {
width: 40px;
@ -659,7 +676,7 @@
top: 125px;
}
* #turf-list.section-editable .turf-block.turf-selected {
background-color: gray;
background-color: #999;
}
* #turf-list.section-editable .turf-block .turf-description {
border: none;
@ -769,5 +786,42 @@
font-size: 20px;
color: #191813;
}
* .edgeflaw input {
display: none;
}
* .edgeflaw input:checked + label {
color: red;
}
* #gang-expert-type-selector #gang-type-boxes {
flex-wrap: wrap;
}
* .cohorts {
flex-wrap: wrap;
}
* .cohorts .cohort-block-wrapper {
width: 400px;
}
* .cohorts .label-stripe {
margin-bottom: 0px;
}
* .cohorts .cohort-body > div {
margin-bottom: 10px;
}
* .cohorts .cohort-block-harm {
justify-content: space-around;
}
* .cohorts .cohort-block-harm input[type=radio] {
display: none;
}
* .cohorts .cohort-block-harm input[type=radio]:checked + label {
color: #EEEFFF;
font-weight: bold;
background-color: #191813;
}
* .cohorts .cohort-block-harm label {
border: 2px solid #191813;
border-top: none;
padding: 5px;
}
/*# sourceMappingURL=style.css.map */
/*# sourceMappingURL=blades.css.map */

1
styles/blades.css.map Normal file
View file

@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["../scss/mixin.scss","../scss/style.scss"],"names":[],"mappings":"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","file":"blades.css"}

View file

@ -1,144 +0,0 @@
.worldbuilding.sheet .window-content {
padding: 5px;
overflow-y: hidden;
}
/* Sheet Header */
.worldbuilding.sheet .sheet-header {
overflow: hidden;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
flex: 0 0 100px;
margin-bottom: 10px;
}
.worldbuilding.sheet .profile-img {
flex: 0 0 100px;
height: 100px;
margin-right: 10px;
}
.worldbuilding.sheet .header-fields {
flex: 1;
height: 100px;
}
.worldbuilding.sheet .charname {
height: 60px;
padding: 5px;
margin: 0;
border-bottom: 0;
}
.worldbuilding.sheet .charname input {
width: 100%;
height: 100%;
margin: 0;
}
.worldbuilding.sheet .resource {
height: 40px;
width: 50%;
padding: 3px 10px;
float: left;
}
.worldbuilding.sheet .resource input {
width: 100px;
height: 28px;
}
/* Navigation Tabs */
.worldbuilding.sheet .tabs {
flex: 0 0 40px;
border-top: 1px solid #AAA;
border-bottom: 1px solid #AAA;
}
.worldbuilding.sheet .tabs .item {
line-height: 40px;
font-weight: bold;
}
.worldbuilding.sheet .tabs .item.active {
text-decoration: underline;
text-shadow: none;
}
/* Content Tabs */
.worldbuilding.sheet .sheet-body {
height: calc(100% - 160px);
}
.worldbuilding.sheet .sheet-body .tab {
height: 100%;
}
.worldbuilding.sheet .sheet-body .editor {
width: 100%;
height: 100%;
}
/* Items */
.worldbuilding.sheet .items-list {
list-style: none;
margin: 7px 0;
padding: 0;
overflow-y: auto;
}
.worldbuilding.sheet .items-list .item {
height: 30px;
line-height: 24px;
padding: 3px 0;
border-bottom: 1px solid #BBB;
}
.worldbuilding.sheet .items-list .item img {
flex: 0 0 24px;
margin-right: 5px;
}
.worldbuilding.sheet .items-list .item-name {
margin: 0;
}
.worldbuilding.sheet .items-list .item-controls {
flex: 0 0 36px;
}
/* Attributes */
.worldbuilding.sheet .attributes-header {
padding: 5px;
margin: 5px 0;
background: rgba(0, 0, 0, 0.05);
border: 1px solid #AAA;
border-radius: 2px;
text-align: center;
font-weight: bold;
}
.worldbuilding.sheet .attribute-label {
flex: 1.5;
}
.worldbuilding.sheet .attribute-control {
flex: 0 0 20px;
}
.worldbuilding.sheet .attributes-list {
list-style: none;
margin: 0;
padding: 0;
}
.worldbuilding.sheet .attributes-list li > * {
margin: 0 3px;
height: 28px;
line-height: 24px;
background: transparent;
border: none;
border-radius: 0;
border-bottom: 1px solid #AAA;
}
.worldbuilding.sheet .attribute-value.checkbox {
text-align: center;
}
.worldbuilding.sheet .attributes-list li a.attribute-control {
border: none;
}

View file

@ -137,8 +137,111 @@
},
"cohort": {
"templates": ["default"],
"type": [],
"cohort_types": ["gang", "expert"]
"cohort": ["Gang"],
"scale": 0,
"quality": 0,
"cohort_list": {
"Gang": {
"label": "Gang"
},
"Expert": {
"label": "Expert"
}
},
"gang_type": ["Adepts"],
"gang_type_list": {
"Adepts": {
"label": "Adepts",
"description": "Scholars, tinkerers, occultists, and chemists."
},
"Rooks": {
"label": "Rooks",
"description": "Con artists, spies, and socialites."
},
"Rovers": {
"label": "Rovers",
"description": "Sailors, carriage drivers, and deathlands scavengers."
},
"Skulks": {
"label": "Skulks",
"description": "Scouts, infiltrators, and thieves."
},
"Thugs": {
"label": "Thugs",
"description": "Scouts, infiltrators, and thieves."
}
},
"expert_type": "",
"status": [],
"statuses": [],
"edges": [],
"edges_list": {
"Fearsome": {
"label": "Fearsome",
"description": "The cohort is terrifying in aspect and reputation."
},
"Independent": {
"label": "Independent",
"description": "The cohort can be trusted to make good decisions and act on their own initiative in the absence of direct orders."
},
"Loyal": {
"label": "Loyal",
"description": "The cohort cant be bribed or turned against you."
},
"Tenacious": {
"label": "Tenacious",
"description": "The cohort wont be deterred from a task."
}
},
"flaws": [],
"flaws_list": {
"Principled": {
"label": "Principled",
"description": "The cohort has an ethic or values that it wont betray."
},
"Savage": {
"label": "Savage",
"description": "The cohort is excessively violent and cruel."
},
"Unreliable": {
"label": "Unreliable",
"description": "The cohort isnt always available, due to other obligations, stupefaction from their vices, etc."
},
"Wild": {
"label": "Wild",
"description": "The cohort is drunken, debauched, and loud-mouthed."
}
},
"harm": ["No"],
"harm_list": {
"No": {
"label": "No Harm",
"description": "The cohort is healthy.",
"value": 0
},
"Weakened": {
"label": "Weakened",
"description": "The cohort has reduced effect.",
"value": 1
},
"Impaired": {
"label": "Impaired",
"description": "The cohort operates with reduced quality (-1d).",
"value": 2
},
"Broken": {
"label": "Broken",
"description": "The cohort cant do anything until they recover.",
"value": 3
},
"Dead": {
"label": "Dead",
"description": "The cohort is destroyed. You can spend coin equal to your Tier +2 to restore it, plus two downtime activities to recruit new gang members, or hire a new expert.",
"value": 4
}
},
"armor": false
},
"crew_feature": {
"templates": ["default"]

View file

@ -13,7 +13,7 @@
{{#each actor.items as |item id|}}
{{#eq item.type "crew_feature"}}
<div class="item flex-horizontal" data-item-id="{{item._id}}">
<div class="item-body flex-horizontal">
<div class="item-body item-sheet-open flex-horizontal">
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24"/>
<div class="item-name">{{item.name}}</div>
</div>
@ -212,6 +212,8 @@
<a class="item" data-tab="turfs">Turfs</a>
<a class="item" data-tab="upgrades">Upgrades</a>
<a class="item" data-tab="abilities">Abilities</a>
<a class="item" data-tab="cohorts">Cohorts</a>
<a class="item" data-tab="notes">Notes</a>
<a class="item" data-tab="all-items">All Items</a>
</nav>
</div>
@ -268,7 +270,7 @@
{{#each actor.items as |item id|}}
{{#eq item.type "crew_upgrade"}}
<div class="item flex-horizontal" data-item-id="{{item._id}}">
<div class="item-body flex-horizontal">
<div class="item-body item-sheet-open flex-horizontal">
<b><div class="item-name">{{item.name}}</div></b>
<div class="item-description">{{item.data.description}}</div>
</div>
@ -286,7 +288,7 @@
{{#each actor.items as |item id|}}
{{#eq item.type "crew_ability"}}
<div class="item flex-horizontal" data-item-id="{{item._id}}">
<div class="item-body flex-horizontal">
<div class="item-body item-sheet-open flex-horizontal">
<b><div class="item-name">{{item.name}}</div></b>
<div class="item-description">{{item.data.description}}</div>
</div>
@ -296,14 +298,37 @@
{{/each}}
</div>
{{!-- Cohorts --}}
<div id="crew-cohorts" class="tab grow-two flex-vertical" data-tab="cohorts">
<div class="label-stripe flex-horizontal">
<p>Cohorts</p>
<p><a class="add-item" data-item-type="cohort"><i class="fas fa-plus-square"></i></a></p>
</div>
<div class="cohorts flex-horizontal">
{{#each actor.items as |item id|}}
{{#eq item.type "cohort"}}
{{> "systems/blades-in-the-dark/templates/parts/cohort-block.html" item=item}}
{{/eq}}
{{/each}}
</div>
</div>
{{!-- Notes --}}
<div id="notes" class="tab grow-two flex-vertical" data-tab="notes">
<label>Notes</label>
<textarea rows="15" name="data.description">{{{data.description}}}</textarea>
</div>
{{!-- Full Item List --}}
<div id="crew-abilities" class="tab grow-two flex-vertical" data-tab="all-items">
<div class="label-stripe">
<p><label>Special Abilities</label></p>
<p><label>All Items</label></p>
</div>
{{#each actor.items as |item id|}}
<div class="item flex-horizontal" data-item-id="{{item._id}}">
<div class="item-body flex-horizontal">
<div class="item-body item-sheet-open flex-horizontal">
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24"/>
<div class="item-name">{{item.name}}</div>
</div>

130
templates/items/cohort.html Normal file
View file

@ -0,0 +1,130 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name"/></h1>
</div>
</header>
<section class="flex-vertical">
<div class="label-stripe">Information</div>
<div>
You can add an additional type to a gang or expert by spending two crew upgrades.
<br>
When a cohort performs actions for which its types apply, it uses its full quality rating. Otherwise, its quality is zero. A given cohort can have up to two types.
Some crew upgrades will add the “Elite” feature to a gang, which gives them +1d when they roll for a given Type.
</div>
</section>
<section class="flex-vertical">
<div class="label-stripe">Cohort Type</div>
<div id="cohort-type-list">
{{#each data.cohort_list as |cohort key|}}
{{#multiboxes ../data.cohort}}
<label for="{{key}}-cohort">{{cohort.label}}</label>
<input id="{{key}}-cohort" type="radio" name="data.cohort" value="{{key}}">
{{/multiboxes}}
{{/each}}
</div>
</section>
<section id="gang-expert-type-selector" class="flex-vertical">
{{#eq data.cohort.[0] "Gang"}}
<div class="label-stripe">Gang Type</div>
<div id="gang-type-boxes" class="flex-horizontal">
{{#multiboxes ../data.gang_type}}
{{#each ../../data.gang_type_list as |gang_type key|}}
<input id="gang-type-{{key}}" type="checkbox" name="data.gang_type" value="{{key}}">
<label for="gang-type-{{key}}">{{gang_type.label}}</label>
{{/each}}
{{/multiboxes}}
</div>
<div id="selected-gang-description" class="description">
{{#each ../data.gang_type as |gang_type key|}}
{{#with (lookup ../../data.gang_type_list gang_type)}}
{{description}}
{{/with}}
{{/each}}
</div>
{{/eq}}
{{#eq data.cohort.[0] "Expert"}}
<div class="label-stripe">Expert Type</div>
<input type="text" name="data.expert_type" value="{{../data.expert_type}}">
{{/eq}}
</section>
{{!-- Scale and Quality if attached to Actor --}}
{{#if data.quality}}
<section id="quality-scale" class="flex-vertical">
<div class="label-stripe">Scale and quality</div>
<div>Quality: {{data.quality}}</div>
<div>Scale: {{data.scale}}</div>
</section>
{{/if}}
{{!-- Edges and Flaws --}}
<section id="edges-flaws" class="flex-vertical">
<div class="label-stripe">Choose one or two edges and an equal number of flaws</div>
<div class="flex-horizontal">
<div class="edgeflaw-container flex-vertical">
<div class="label-stripe">Edges</div>
{{#each data.edges_list as |edge key|}}
{{#multiboxes ../data.edges}}
<div class="edgeflaw flex-horizontal">
<input id="edge-{{key}}" type="checkbox" name="data.edges" value="{{key}}">
<label for="edge-{{key}}">{{edge.label}}</label>
</div>
{{/multiboxes}}
{{/each}}
</div>
<div class="edgeflaw-container flex-vertical">
<div class="label-stripe">Flaws</div>
{{#each data.flaws_list as |flaw key|}}
{{#multiboxes ../data.flaws}}
<div class="edgeflaw flex-horizontal">
<input id="flaw-{{key}}" type="checkbox" name="data.flaws" value="{{key}}">
<label for="flaw-{{key}}">{{flaw.label}}</label>
</div>
{{/multiboxes}}
{{/each}}
</div>
</div>
</section>
<section id="cohort-harm" class="flex-vertical">
<div class="label-stripe">Harm</div>
<div id="harm-list" class="flex-horizontal">
{{#multiboxes data.harm}}
{{#each data.harm_list as |harm harm_key|}}
<input id="{{harm_key}}-harm" type="radio" name="data.harm" value="{{harm_key}}">
<label for="{{harm_key}}-harm">{{harm.label}}</label>
{{/each}}
{{/multiboxes}}
</div>
</section>
<section>
<input id="cohort-armor" type="checkbox" name="data.armor" value="{{data.armor}}" {{checked data.armor}}>
<label for="cohort-armor">Armor</label>
</section>
<section class="sheet-body flex-vertical">
<div class="label-stripe">Description</div>
<textarea name="data.description">{{data.description}}</textarea>
</section>
</form>

View file

@ -0,0 +1,47 @@
<div class="item cohort-block-wrapper" data-item-id="{{item._id}}">
<div class="cohort-block">
<div class="label-stripe">
<div class="item-sheet-open">{{#eq item.data.cohort.[0] "Gang"}}Gang of {{#each ../item.data.gang_type as |gang_type key|}}{{gang_type}} {{/each}}{{/eq}}{{#eq item.data.cohort.[0] "Expert"}}{{../item.data.cohort.[0]}} {{../item.data.expert_type}}{{/eq}} (click to edit)</div>
<div>Q:{{item.data.quality}} S:{{item.data.scale}}</div>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
<div class="cohort-body">
<div class="cohort-block-harm flex-horizontal">
{{#each item.data.harm_list as |harm harm_key|}}
{{#multiboxes ../item.data.harm}}
<input id="harm-{{harm_key}}-{{../item._id}}" type="radio" name="harm.{{../item._id}}" data-item="{{../item._id}}" value="{{harm_key}}">
<label for="harm-{{harm_key}}-{{../item._id}}">{{harm.label}}</label>
{{/multiboxes}}
{{/each}}
</div>
{{#eq item.data.cohort.[0] "Gang"}}
{{#each ../item.data.gang_type as |gang_type key|}}
<div>
{{#with (lookup ../../item.data.gang_type_list gang_type)}}{{description}} {{/with}}
</div>
{{/each}}
{{/eq}}
<div class="flex-vertical">
<div class="flex-vertical">
{{#each item.data.edges as |edge key|}}
{{#with (lookup ../item.data.edges_list edge)}}
<div class="description">{{description}} <b>({{label}})</b></div>
{{/with}}
{{/each}}
{{#each item.data.flaws as |flaw key|}}
{{#with (lookup ../item.data.flaws_list flaw)}}
<div class="description">{{description}} <b>({{label}})</b></div>
{{/with}}
{{/each}}
</div>
</div>
<div class="description">{{item.data.description}}</div>
</div>
</div>
</div>