mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-23 15:48:11 -05:00
Refactored and improved the ThangComponentsEditView and ThangComponentConfigView. Still some things to do.
This commit is contained in:
parent
9a1dd412c9
commit
6cac2371c1
25 changed files with 597 additions and 584 deletions
|
@ -3,7 +3,7 @@ c = require './../schemas'
|
||||||
module.exports = ThangComponentSchema = c.object {
|
module.exports = ThangComponentSchema = c.object {
|
||||||
title: 'Component'
|
title: 'Component'
|
||||||
description: 'Configuration for a Component that this Thang uses.'
|
description: 'Configuration for a Component that this Thang uses.'
|
||||||
format: 'thang-component'
|
format: 'component-reference'
|
||||||
required: ['original', 'majorVersion']
|
required: ['original', 'majorVersion']
|
||||||
'default':
|
'default':
|
||||||
majorVersion: 0
|
majorVersion: 0
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#component-config-column-view
|
|
||||||
h3
|
|
||||||
float: left
|
|
||||||
#add-remove-button
|
|
||||||
float: right
|
|
||||||
margin: 5px
|
|
||||||
#description
|
|
||||||
clear: both
|
|
||||||
|
|
||||||
.treema
|
|
||||||
position: absolute
|
|
||||||
left: 5px
|
|
||||||
right: 5px
|
|
||||||
top: 90px
|
|
||||||
bottom: 0
|
|
||||||
overflow: scroll
|
|
|
@ -0,0 +1 @@
|
||||||
|
//.thang-component-config-view
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#extant-components-column
|
#extant-components-column
|
||||||
left: 0
|
left: 0
|
||||||
width: 20%
|
width: 300px
|
||||||
|
|
||||||
.treema
|
.treema
|
||||||
position: absolute
|
position: absolute
|
||||||
|
@ -29,26 +29,23 @@
|
||||||
bottom: 0
|
bottom: 0
|
||||||
overflow: scroll
|
overflow: scroll
|
||||||
|
|
||||||
#add-component-column
|
.dependent
|
||||||
right: 0
|
background-color: rgba(128, 64, 255, 0.10)
|
||||||
width: 20%
|
|
||||||
|
|
||||||
.treema
|
#thang-components-config-column
|
||||||
|
border-left: 1px solid black
|
||||||
|
right: 0
|
||||||
|
left: 300px
|
||||||
|
min-width: 600px
|
||||||
|
|
||||||
|
h3
|
||||||
|
margin-left: 20px
|
||||||
|
|
||||||
|
#thang-component-configs
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 75px
|
top: 80px
|
||||||
left: 10px
|
|
||||||
right: 0px
|
|
||||||
bottom: 0
|
bottom: 0
|
||||||
|
right: 0
|
||||||
|
left: 20px
|
||||||
overflow: scroll
|
overflow: scroll
|
||||||
|
|
||||||
.treema-row
|
|
||||||
line-height: 24px
|
|
||||||
.add-button
|
|
||||||
margin-left: 10px
|
|
||||||
|
|
||||||
#component-config-column-view
|
|
||||||
border-left: 1px solid black
|
|
||||||
border-right: 1px solid black
|
|
||||||
right: 20%
|
|
||||||
left: 20%
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#editor-level-view
|
.editor
|
||||||
&, #level-editor-top-nav
|
h1, h2, h3, h4, h5, h6, a
|
||||||
// min-width: 1024px
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important
|
||||||
|
|
||||||
a
|
|
||||||
font-family: helvetica, arial, sans serif
|
|
||||||
|
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 0px
|
top: 0px
|
||||||
|
@ -48,7 +45,7 @@
|
||||||
border-radius: 0
|
border-radius: 0
|
||||||
.navbar-right
|
.navbar-right
|
||||||
// not sure why bootstrap puts a big negative margin in, but this overrides it
|
// not sure why bootstrap puts a big negative margin in, but this overrides it
|
||||||
margin-right: 10px
|
margin-right: 10px !important
|
||||||
float: right
|
float: right
|
||||||
|
|
||||||
.dropdown-menu
|
.dropdown-menu
|
||||||
|
@ -130,9 +127,7 @@
|
||||||
margin-top: -10px
|
margin-top: -10px
|
||||||
padding-top: 10px
|
padding-top: 10px
|
||||||
|
|
||||||
// keeps the editor tabs a certain height
|
#level-editor-tabs, #thang-type-edit-view .tab-content
|
||||||
|
|
||||||
#level-editor-tabs
|
|
||||||
position: absolute
|
position: absolute
|
||||||
left: 15px
|
left: 15px
|
||||||
right: 15px
|
right: 15px
|
|
@ -1,85 +0,0 @@
|
||||||
#editor-thang-type-edit-view
|
|
||||||
#save-button, #revert-button
|
|
||||||
float: right
|
|
||||||
margin-right: 20px
|
|
||||||
|
|
||||||
#portrait
|
|
||||||
float: right
|
|
||||||
|
|
||||||
.main-area
|
|
||||||
padding: 5px
|
|
||||||
& > div.slider-cell
|
|
||||||
margin-right: 5px
|
|
||||||
float: right
|
|
||||||
.file-controls
|
|
||||||
float: left
|
|
||||||
position: relative
|
|
||||||
top: 5px
|
|
||||||
left: 5px
|
|
||||||
button
|
|
||||||
margin-left: 5px
|
|
||||||
select
|
|
||||||
position: relative
|
|
||||||
top: 5px
|
|
||||||
input
|
|
||||||
display: none
|
|
||||||
|
|
||||||
.slider-cell
|
|
||||||
margin: 5px 0
|
|
||||||
float: left
|
|
||||||
width: 120px
|
|
||||||
|
|
||||||
.selector
|
|
||||||
display: inline-block
|
|
||||||
width: 100px
|
|
||||||
position: relative
|
|
||||||
top: 3px
|
|
||||||
|
|
||||||
#marker-button, #end-button
|
|
||||||
float: right
|
|
||||||
margin-right: 10px
|
|
||||||
position: relative
|
|
||||||
top: 15px
|
|
||||||
|
|
||||||
#canvas
|
|
||||||
float: right
|
|
||||||
width: 400px
|
|
||||||
border: 1px solid blue
|
|
||||||
background-color: lightgray
|
|
||||||
|
|
||||||
#settings-col
|
|
||||||
float: left
|
|
||||||
width: 550px
|
|
||||||
|
|
||||||
.treema-row img
|
|
||||||
max-width: 100%
|
|
||||||
|
|
||||||
#thang-type-treema
|
|
||||||
height: 400px
|
|
||||||
overflow: scroll
|
|
||||||
box-sizing: border-box
|
|
||||||
|
|
||||||
|
|
||||||
#thang-components-edit-view
|
|
||||||
position: absolute
|
|
||||||
top: 200px
|
|
||||||
bottom: 0
|
|
||||||
|
|
||||||
.treema-root
|
|
||||||
background-color: white
|
|
||||||
border-radius: 4px
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#spritesheets
|
|
||||||
border: 1px solid green
|
|
||||||
max-width: 100%
|
|
||||||
max-height: 600px
|
|
||||||
overflow: scroll
|
|
||||||
clear: both
|
|
||||||
box-sizing: border-box
|
|
||||||
margin-bottom: 20px
|
|
||||||
canvas
|
|
||||||
background: darkseagreen
|
|
||||||
margin: 2px
|
|
||||||
|
|
92
app/styles/editor/thang/thang-type-edit-view.sass
Normal file
92
app/styles/editor/thang/thang-type-edit-view.sass
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#thang-type-edit-view
|
||||||
|
#portrait
|
||||||
|
float: left
|
||||||
|
margin: 5px
|
||||||
|
width: 100px
|
||||||
|
height: 100px
|
||||||
|
|
||||||
|
#settings-col
|
||||||
|
width: 560px
|
||||||
|
position: absolute
|
||||||
|
left: 0
|
||||||
|
top: 0
|
||||||
|
bottom: 0
|
||||||
|
|
||||||
|
.file-controls
|
||||||
|
float: left
|
||||||
|
position: relative
|
||||||
|
top: 5px
|
||||||
|
left: 5px
|
||||||
|
button
|
||||||
|
margin-left: 5px
|
||||||
|
input
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.treema-row img
|
||||||
|
max-width: 100%
|
||||||
|
|
||||||
|
.treema-root
|
||||||
|
overflow: scroll
|
||||||
|
box-sizing: border-box
|
||||||
|
position: absolute
|
||||||
|
top: 160px
|
||||||
|
bottom: 20px
|
||||||
|
right: 20px
|
||||||
|
left: 20px
|
||||||
|
|
||||||
|
#display-col
|
||||||
|
position: absolute
|
||||||
|
width: 440px
|
||||||
|
left: 580px
|
||||||
|
top: 0
|
||||||
|
bottom: 0
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
& > div.slider-cell
|
||||||
|
margin-right: 5px
|
||||||
|
|
||||||
|
canvas
|
||||||
|
width: 400px
|
||||||
|
border: 1px solid blue
|
||||||
|
background-color: lightgray
|
||||||
|
|
||||||
|
select
|
||||||
|
margin-top: 10px
|
||||||
|
|
||||||
|
#marker-button, #end-button
|
||||||
|
margin: 10px 10px 10px 0
|
||||||
|
|
||||||
|
.slider-cell
|
||||||
|
margin: 5px 0
|
||||||
|
width: 195px
|
||||||
|
float: left
|
||||||
|
|
||||||
|
.selector
|
||||||
|
display: inline-block
|
||||||
|
width: 180px
|
||||||
|
position: relative
|
||||||
|
top: 3px
|
||||||
|
|
||||||
|
|
||||||
|
#thang-components-edit-view
|
||||||
|
position: absolute
|
||||||
|
top: 0px
|
||||||
|
bottom: 0
|
||||||
|
|
||||||
|
.treema-root
|
||||||
|
background-color: white
|
||||||
|
border-radius: 4px
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#spritesheets
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
bottom: 0
|
||||||
|
left: 0
|
||||||
|
right: 0
|
||||||
|
border: 1px solid green
|
||||||
|
overflow: scroll
|
||||||
|
canvas
|
||||||
|
background: darkseagreen
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
&, & > div.ace_editor
|
&, & > div.ace_editor
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
& > div.ace_editor
|
|
||||||
height: 400px
|
|
||||||
|
|
||||||
.treema-markdown.treema-display, .treema-coffee.treema-display, .treema-javascript.treema-display
|
.treema-markdown.treema-display, .treema-coffee.treema-display, .treema-javascript.treema-display
|
||||||
width: 100%
|
width: 100%
|
||||||
border: 3px inset rgba(0, 100, 100, 0.2)
|
border: 3px inset rgba(0, 100, 100, 0.2)
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
h3= component.name
|
|
||||||
//button.btn#add-remove-button Add Component
|
|
||||||
p#description= component.description
|
|
||||||
.treema
|
|
||||||
//p#other-props
|
|
||||||
// strong Other Config Properties:
|
|
||||||
// for prop in configProperties
|
|
||||||
// a(title=prop.description)= prop.name
|
|
|
@ -1,11 +0,0 @@
|
||||||
#extant-components-column.column
|
|
||||||
h3 Components
|
|
||||||
p Click then press delete to remove.
|
|
||||||
.treema
|
|
||||||
|
|
||||||
#component-config-column-view.column
|
|
||||||
|
|
||||||
#add-component-column.column
|
|
||||||
h3 Add Components
|
|
||||||
p Click then press enter to add.
|
|
||||||
.treema
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
.panel.panel-default
|
||||||
|
.panel-heading
|
||||||
|
strong.panel-title= component.name
|
||||||
|
em.spl.spr (#{component.system})
|
||||||
|
span#description= component.description
|
||||||
|
.panel-body
|
||||||
|
.treema
|
|
@ -0,0 +1,9 @@
|
||||||
|
#extant-components-column.column
|
||||||
|
h3 Components
|
||||||
|
p Click then press delete to remove.
|
||||||
|
.treema
|
||||||
|
|
||||||
|
.column#thang-components-config-column
|
||||||
|
h3 Component Configurations
|
||||||
|
#thang-component-configs
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
extends /templates/base
|
|
||||||
|
|
||||||
block content
|
|
||||||
div
|
|
||||||
ol.breadcrumb
|
|
||||||
li
|
|
||||||
a(href="/editor", data-i18n="editor.main_title") CodeCombat Editors
|
|
||||||
li
|
|
||||||
a(href="/editor/thang", data-i18n="editor.thang_title") Thang Editor
|
|
||||||
li.active
|
|
||||||
| #{thangType.attributes.name}
|
|
||||||
|
|
||||||
img#portrait.img-thumbnail
|
|
||||||
|
|
||||||
button.btn.btn-secondary#history-button(data-i18n="general.version_history") Version History
|
|
||||||
button.btn.btn-primary#save-button(data-i18n="common.save", disabled=authorized === true ? undefined : "true") Save
|
|
||||||
button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true") Revert
|
|
||||||
|
|
||||||
h3 Edit Thang Type: "#{thangType.attributes.name}"
|
|
||||||
|
|
||||||
ul.nav.nav-tabs
|
|
||||||
li.active
|
|
||||||
a(href="#editor-thang-main-tab-view", data-toggle="tab") Main
|
|
||||||
li
|
|
||||||
a(href="#editor-thang-components-tab-view", data-toggle="tab") Components
|
|
||||||
li
|
|
||||||
a(href="#editor-thang-spritesheets-view", data-toggle="tab") Spritesheets
|
|
||||||
li
|
|
||||||
a(href="#editor-thang-colors-tab-view", data-toggle="tab")#color-tab Colors
|
|
||||||
li
|
|
||||||
a(href="#editor-thang-patches-view", data-toggle="tab")#patches-tab Patches
|
|
||||||
|
|
||||||
div.tab-content
|
|
||||||
div.tab-pane#editor-thang-colors-tab-view
|
|
||||||
|
|
||||||
div.tab-pane#editor-thang-main-tab-view.active
|
|
||||||
|
|
||||||
div.main-area.well
|
|
||||||
div.file-controls
|
|
||||||
select#animations-select
|
|
||||||
for animation in animations
|
|
||||||
option #{animation}
|
|
||||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-primary#upload-button
|
|
||||||
i.icon-upload
|
|
||||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-primary#clear-button
|
|
||||||
i.icon-remove
|
|
||||||
input#real-upload-button(type="file")
|
|
||||||
|
|
||||||
button.btn.btn-small.btn-primary#marker-button
|
|
||||||
i.icon-map-marker
|
|
||||||
|
|
||||||
button.btn.btn-small.btn-primary#end-button
|
|
||||||
i.icon-stop
|
|
||||||
|
|
||||||
div.slider-cell
|
|
||||||
| Rotation:
|
|
||||||
span.rotation-label
|
|
||||||
.selector#rotation-slider
|
|
||||||
div.slider-cell
|
|
||||||
| Scale:
|
|
||||||
span.scale-label
|
|
||||||
.selector#scale-slider
|
|
||||||
div.slider-cell
|
|
||||||
| Resolution:
|
|
||||||
span.resolution-label 4.0x
|
|
||||||
.selector#resolution-slider
|
|
||||||
div.slider-cell
|
|
||||||
| Health:
|
|
||||||
span.health-label 10hp
|
|
||||||
.selector#health-slider
|
|
||||||
|
|
||||||
.clearfix
|
|
||||||
|
|
||||||
div#settings-col
|
|
||||||
div#thang-type-treema
|
|
||||||
|
|
||||||
canvas#canvas(width="400", height="400")
|
|
||||||
|
|
||||||
.clearfix
|
|
||||||
|
|
||||||
div.tab-pane#editor-thang-components-tab-view
|
|
||||||
|
|
||||||
#thang-components-edit-view
|
|
||||||
|
|
||||||
div.tab-pane#editor-thang-spritesheets-view
|
|
||||||
|
|
||||||
div#spritesheets
|
|
||||||
|
|
||||||
div.tab-pane#editor-thang-patches-view
|
|
||||||
|
|
||||||
div.patches-view
|
|
||||||
|
|
||||||
div#error-view
|
|
||||||
|
|
||||||
.clearfix
|
|
124
app/templates/editor/thang/thang-type-edit-view.jade
Normal file
124
app/templates/editor/thang/thang-type-edit-view.jade
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
extends /templates/base
|
||||||
|
block header
|
||||||
|
if thangType.loading
|
||||||
|
nav.navbar.navbar-default(role='navigation')#thang-editor-top-nav
|
||||||
|
.container-fluid
|
||||||
|
ul.nav.navbar-nav
|
||||||
|
li
|
||||||
|
a(href="/editor/thang")
|
||||||
|
span.glyphicon-home.glyphicon
|
||||||
|
else
|
||||||
|
nav.navbar.navbar-default(role='navigation')#thang-editor-top-nav
|
||||||
|
ul.nav.navbar-nav
|
||||||
|
li
|
||||||
|
a(href="/editor/thang")
|
||||||
|
span.glyphicon-home.glyphicon
|
||||||
|
ul.nav.navbar-nav.nav-tabs
|
||||||
|
li.active
|
||||||
|
a(href="#editor-thang-main-tab-view", data-toggle="tab") Main
|
||||||
|
li
|
||||||
|
a(href="#editor-thang-components-tab-view", data-toggle="tab") Components
|
||||||
|
li
|
||||||
|
a(href="#editor-thang-spritesheets-view", data-toggle="tab") Spritesheets
|
||||||
|
li
|
||||||
|
a(href="#editor-thang-colors-tab-view", data-toggle="tab")#color-tab Colors
|
||||||
|
li
|
||||||
|
a(href="#editor-thang-patches-view", data-toggle="tab")#patches-tab
|
||||||
|
span(data-i18n="resources.patches").spr Patches
|
||||||
|
- var patches = thangType.get('patches')
|
||||||
|
if patches && patches.length
|
||||||
|
span.badge= patches.length
|
||||||
|
|
||||||
|
.navbar-header
|
||||||
|
span.navbar-brand #{thangType.attributes.name}
|
||||||
|
|
||||||
|
ul.nav.navbar-nav.navbar-right
|
||||||
|
if authorized
|
||||||
|
li#save-button
|
||||||
|
a
|
||||||
|
span.glyphicon-floppy-disk.glyphicon
|
||||||
|
li.dropdown
|
||||||
|
a(data-toggle='dropdown')
|
||||||
|
span.glyphicon-chevron-down.glyphicon
|
||||||
|
ul.dropdown-menu
|
||||||
|
li.dropdown-header Actions
|
||||||
|
li(class=anonymous ? "disabled": "")
|
||||||
|
a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert")#revert-button Revert
|
||||||
|
li.divider
|
||||||
|
li.dropdown-header Info
|
||||||
|
li#history-button
|
||||||
|
a(href='#', data-i18n="general.version_history") Version History
|
||||||
|
li.divider
|
||||||
|
li.dropdown-header Help
|
||||||
|
li
|
||||||
|
a(href='https://github.com/codecombat/codecombat/wiki/Artisan-Home', data-i18n="editor.wiki", target="_blank") Wiki
|
||||||
|
li
|
||||||
|
a(href='http://www.hipchat.com/g3plnOKqa', data-i18n="editor.live_chat", target="_blank") Live Chat
|
||||||
|
li
|
||||||
|
a(href='http://discourse.codecombat.com/category/artisan', data-i18n="nav.forum", target="_blank") Forum
|
||||||
|
li
|
||||||
|
a(data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Email
|
||||||
|
|
||||||
|
block outer_content
|
||||||
|
.outer-content
|
||||||
|
div.tab-content
|
||||||
|
div.tab-pane#editor-thang-colors-tab-view
|
||||||
|
div.tab-pane#editor-thang-main-tab-view.active
|
||||||
|
div#settings-col.well
|
||||||
|
img#portrait.img-thumbnail
|
||||||
|
div.file-controls
|
||||||
|
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-info#upload-button
|
||||||
|
span.glyphicon.glyphicon-upload
|
||||||
|
span.spl Upload Animation
|
||||||
|
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-danger#clear-button
|
||||||
|
span.glyphicon.glyphicon-remove
|
||||||
|
span.spl Clear Data
|
||||||
|
input#real-upload-button(type="file")
|
||||||
|
div#thang-type-treema
|
||||||
|
.clearfix
|
||||||
|
div#display-col.well
|
||||||
|
canvas#canvas(width="400", height="400")
|
||||||
|
select#animations-select.form-control
|
||||||
|
for animation in animations
|
||||||
|
option #{animation}
|
||||||
|
div
|
||||||
|
button.btn.btn-small.btn-primary#marker-button
|
||||||
|
i.icon-map-marker
|
||||||
|
span.spl Markers
|
||||||
|
button.btn.btn-small.btn-primary#end-button
|
||||||
|
i.icon-stop
|
||||||
|
span.spl Stop
|
||||||
|
div.slider-cell
|
||||||
|
| Rotation:
|
||||||
|
span.rotation-label
|
||||||
|
.selector#rotation-slider
|
||||||
|
div.slider-cell
|
||||||
|
| Scale:
|
||||||
|
span.scale-label
|
||||||
|
.selector#scale-slider
|
||||||
|
div.slider-cell
|
||||||
|
| Resolution:
|
||||||
|
span.resolution-label 4.0x
|
||||||
|
.selector#resolution-slider
|
||||||
|
div.slider-cell
|
||||||
|
| Health:
|
||||||
|
span.health-label 10hp
|
||||||
|
.selector#health-slider
|
||||||
|
|
||||||
|
div.tab-pane#editor-thang-components-tab-view
|
||||||
|
#thang-components-edit-view
|
||||||
|
div.tab-pane#editor-thang-spritesheets-view
|
||||||
|
div#spritesheets
|
||||||
|
div.tab-pane#editor-thang-patches-view
|
||||||
|
div.patches-view
|
||||||
|
div#error-view
|
||||||
|
.clearfix
|
||||||
|
block footer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -225,14 +225,8 @@ class CodeTreema extends TreemaNode.nodeMap.ace
|
||||||
super(valEl)
|
super(valEl)
|
||||||
if not @schema.aceMode and mode = codeLanguages[@keyForParent]
|
if not @schema.aceMode and mode = codeLanguages[@keyForParent]
|
||||||
@editor.getSession().setMode mode
|
@editor.getSession().setMode mode
|
||||||
@editor.on('change', @onEditorChange)
|
|
||||||
valEl
|
valEl
|
||||||
|
|
||||||
onEditorChange: =>
|
|
||||||
@saveChanges()
|
|
||||||
@flushChanges()
|
|
||||||
@getRoot().broadcastChanges()
|
|
||||||
|
|
||||||
class CoffeeTreema extends CodeTreema
|
class CoffeeTreema extends CodeTreema
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
|
@ -308,26 +302,19 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
input.focus().keyup @search
|
input.focus().keyup @search
|
||||||
input.attr('placeholder', @formatDocument(@data)) if @data
|
input.attr('placeholder', @formatDocument(@data)) if @data
|
||||||
|
|
||||||
|
buildSearchURL: (term) -> "#{@url}?term=#{term}&project=true"
|
||||||
|
|
||||||
search: =>
|
search: =>
|
||||||
term = @getValEl().find('input').val()
|
term = @getValEl().find('input').val()
|
||||||
return if term is @lastTerm
|
return if term is @lastTerm
|
||||||
|
|
||||||
# HACK while search is broken
|
|
||||||
if @collection
|
|
||||||
@lastTerm = term
|
|
||||||
@searchCallback()
|
|
||||||
return
|
|
||||||
|
|
||||||
@getSearchResultsEl().empty() if @lastTerm and not term
|
@getSearchResultsEl().empty() if @lastTerm and not term
|
||||||
return unless term
|
return unless term
|
||||||
@lastTerm = term
|
@lastTerm = term
|
||||||
@getSearchResultsEl().empty().append('Searching')
|
@getSearchResultsEl().empty().append('Searching')
|
||||||
@collection = new LatestVersionCollection([], model: @model)
|
@collection = new LatestVersionCollection([], model: @model)
|
||||||
|
|
||||||
# HACK while search is broken
|
@collection.url = @buildSearchURL(term)
|
||||||
# @collection.url = "#{@url}?term=#{term}&project=true"
|
|
||||||
@collection.url = "#{@url}?term=#{''}&project=true"
|
|
||||||
|
|
||||||
@collection.fetch()
|
@collection.fetch()
|
||||||
@collection.once 'sync', @searchCallback, @
|
@collection.once 'sync', @searchCallback, @
|
||||||
|
|
||||||
|
@ -338,10 +325,6 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
row = $('<div></div>').addClass('treema-search-result-row')
|
row = $('<div></div>').addClass('treema-search-result-row')
|
||||||
text = @formatDocument(model)
|
text = @formatDocument(model)
|
||||||
continue unless text?
|
continue unless text?
|
||||||
|
|
||||||
# HACK while search is broken
|
|
||||||
continue unless text.toLowerCase().indexOf(@lastTerm.toLowerCase()) >= 0
|
|
||||||
|
|
||||||
row.addClass('treema-search-selected') if first
|
row.addClass('treema-search-selected') if first
|
||||||
first = false
|
first = false
|
||||||
row.text(text)
|
row.text(text)
|
||||||
|
@ -354,9 +337,10 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
getSearchResultsEl: -> @getValEl().find('.treema-search-results')
|
getSearchResultsEl: -> @getValEl().find('.treema-search-results')
|
||||||
getSelectedResultEl: -> @getValEl().find('.treema-search-selected')
|
getSelectedResultEl: -> @getValEl().find('.treema-search-selected')
|
||||||
|
|
||||||
|
modelToString: (model) -> model.get('name')
|
||||||
|
|
||||||
formatDocument: (docOrModel) ->
|
formatDocument: (docOrModel) ->
|
||||||
doc = docOrModel.attributes or docOrModel
|
return @modelToString(docOrModel) if docOrModel instanceof CocoModel
|
||||||
return doc.name if doc.name?
|
|
||||||
return 'Unknown' unless @settings.supermodel?
|
return 'Unknown' unless @settings.supermodel?
|
||||||
m = CocoModel.getReferencedModel(@data, @schema)
|
m = CocoModel.getReferencedModel(@data, @schema)
|
||||||
urlGoingFor = m.url()
|
urlGoingFor = m.url()
|
||||||
|
@ -366,7 +350,7 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
m.url = -> urlGoingFor
|
m.url = -> urlGoingFor
|
||||||
@settings.supermodel.registerModel(m)
|
@settings.supermodel.registerModel(m)
|
||||||
return 'Unknown' unless m
|
return 'Unknown' unless m
|
||||||
return m.get('name')
|
return @modelToString(m)
|
||||||
|
|
||||||
saveChanges: ->
|
saveChanges: ->
|
||||||
selected = @getSelectedResultEl()
|
selected = @getSelectedResultEl()
|
||||||
|
@ -379,10 +363,12 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
@instance = fullValue
|
@instance = fullValue
|
||||||
|
|
||||||
onDownArrowPressed: (e) ->
|
onDownArrowPressed: (e) ->
|
||||||
|
return super(arguments...) unless @isEditing()
|
||||||
@navigateSearch(1)
|
@navigateSearch(1)
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
onUpArrowPressed: (e) ->
|
onUpArrowPressed: (e) ->
|
||||||
|
return super(arguments...) unless @isEditing()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@navigateSearch(-1)
|
@navigateSearch(-1)
|
||||||
|
|
||||||
|
@ -411,6 +397,13 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
selected = @getSelectedResultEl()
|
selected = @getSelectedResultEl()
|
||||||
return not selected.length
|
return not selected.length
|
||||||
|
|
||||||
|
class LevelComponentReferenceNode extends LatestVersionReferenceNode
|
||||||
|
# HACK: this list of properties is needed by the thang components edit view and config views.
|
||||||
|
# need a better way to specify this, or keep the search models from bleeding into those
|
||||||
|
# supermodels.
|
||||||
|
buildSearchURL: (term) -> "#{@url}?term=#{term}&project=name,system,original,version,dependencies,configSchema,description"
|
||||||
|
modelToString: (model) -> model.get('system') + '.' + model.get('name')
|
||||||
|
canEdit: -> not @data.original # only allow editing if the row's data hasn't been set yet
|
||||||
|
|
||||||
LatestVersionReferenceNode.prototype.search = _.debounce(LatestVersionReferenceNode.prototype.search, 200)
|
LatestVersionReferenceNode.prototype.search = _.debounce(LatestVersionReferenceNode.prototype.search, 200)
|
||||||
|
|
||||||
|
@ -431,6 +424,7 @@ module.exports.setup = ->
|
||||||
TreemaNode.setNodeSubclass('javascript', JavaScriptTreema)
|
TreemaNode.setNodeSubclass('javascript', JavaScriptTreema)
|
||||||
TreemaNode.setNodeSubclass('image-file', ImageFileTreema)
|
TreemaNode.setNodeSubclass('image-file', ImageFileTreema)
|
||||||
TreemaNode.setNodeSubclass('latest-version-reference', LatestVersionReferenceNode)
|
TreemaNode.setNodeSubclass('latest-version-reference', LatestVersionReferenceNode)
|
||||||
|
TreemaNode.setNodeSubclass('component-reference', LevelComponentReferenceNode)
|
||||||
TreemaNode.setNodeSubclass('i18n', InternationalizationNode)
|
TreemaNode.setNodeSubclass('i18n', InternationalizationNode)
|
||||||
TreemaNode.setNodeSubclass('sound-file', SoundFileTreema)
|
TreemaNode.setNodeSubclass('sound-file', SoundFileTreema)
|
||||||
TreemaNode.setNodeSubclass 'slug-props', SlugPropsObject
|
TreemaNode.setNodeSubclass 'slug-props', SlugPropsObject
|
||||||
|
|
|
@ -1,28 +1,29 @@
|
||||||
CocoView = require 'views/kinds/CocoView'
|
CocoView = require 'views/kinds/CocoView'
|
||||||
template = require 'templates/editor/components/config'
|
template = require 'templates/editor/components/thang-component-config-view'
|
||||||
|
|
||||||
Level = require 'models/Level'
|
Level = require 'models/Level'
|
||||||
LevelComponent = require 'models/LevelComponent'
|
LevelComponent = require 'models/LevelComponent'
|
||||||
nodes = require '../level/treema_nodes'
|
nodes = require '../level/treema_nodes'
|
||||||
|
|
||||||
module.exports = class ThangComponentConfigView extends CocoView
|
module.exports = class ThangComponentConfigView extends CocoView
|
||||||
id: 'component-config-column-view'
|
className: 'thang-component-config-view'
|
||||||
template: template
|
template: template
|
||||||
className: 'column'
|
|
||||||
changed: false
|
changed: false
|
||||||
|
|
||||||
|
events:
|
||||||
|
'click .treema-shortened': -> console.log 'clicked treema root'
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super options
|
super options
|
||||||
@component = options.component
|
@component = options.component
|
||||||
@config = options.config or {}
|
@config = options.config or {}
|
||||||
@world = options.world
|
@world = options.world
|
||||||
@level = options.level
|
@level = options.level
|
||||||
@editing = options.editing
|
|
||||||
@callback = options.callback
|
@callback = options.callback
|
||||||
|
|
||||||
getRenderData: (context={}) ->
|
getRenderData: (context={}) ->
|
||||||
context = super(context)
|
context = super(context)
|
||||||
context.component = @component
|
context.component = @component.attributes
|
||||||
context.configProperties = []
|
context.configProperties = []
|
||||||
context
|
context
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ module.exports = class ThangComponentConfigView extends CocoView
|
||||||
superteams = _.union(teams, superteams)
|
superteams = _.union(teams, superteams)
|
||||||
treemaOptions =
|
treemaOptions =
|
||||||
supermodel: @supermodel
|
supermodel: @supermodel
|
||||||
schema: @component.configSchema
|
schema: @component.attributes.configSchema
|
||||||
data: _.cloneDeep @config
|
data: _.cloneDeep @config
|
||||||
callbacks: {change: @onConfigEdited}
|
callbacks: {change: @onConfigEdited}
|
||||||
world: @world
|
world: @world
|
||||||
|
@ -58,16 +59,16 @@ module.exports = class ThangComponentConfigView extends CocoView
|
||||||
'seconds': nodes.SecondsNode
|
'seconds': nodes.SecondsNode
|
||||||
'speed': nodes.SpeedNode
|
'speed': nodes.SpeedNode
|
||||||
'acceleration': nodes.AccelerationNode
|
'acceleration': nodes.AccelerationNode
|
||||||
treemaOptions.readOnly = not @editing
|
|
||||||
|
|
||||||
@editThangTreema = @$el.find('.treema').treema treemaOptions
|
@editThangTreema = @$el.find('.treema').treema treemaOptions
|
||||||
@editThangTreema.build()
|
@editThangTreema.build()
|
||||||
@editThangTreema.open(2)
|
@editThangTreema.open(2)
|
||||||
@hideLoading()
|
if _.isEqual(@config, {}) and not @editThangTreema.canAddChild()
|
||||||
|
@$el.find('.panel-body').hide()
|
||||||
|
|
||||||
onConfigEdited: =>
|
onConfigEdited: =>
|
||||||
@changed = true
|
@changed = true
|
||||||
@callback?(@data())
|
@trigger 'changed', { component: @component, config: @data() }
|
||||||
|
|
||||||
undo: ->
|
undo: ->
|
||||||
@editThangTreema.undo()
|
@editThangTreema.undo()
|
||||||
|
|
|
@ -1,284 +0,0 @@
|
||||||
CocoView = require 'views/kinds/CocoView'
|
|
||||||
template = require 'templates/editor/components/main'
|
|
||||||
|
|
||||||
Level = require 'models/Level'
|
|
||||||
LevelComponent = require 'models/LevelComponent'
|
|
||||||
LevelSystem = require 'models/LevelSystem'
|
|
||||||
ComponentsCollection = require 'collections/ComponentsCollection'
|
|
||||||
ComponentConfigView = require './ThangComponentConfigView'
|
|
||||||
|
|
||||||
module.exports = class ThangComponentEditView extends CocoView
|
|
||||||
id: 'thang-components-edit-view'
|
|
||||||
template: template
|
|
||||||
|
|
||||||
constructor: (options) ->
|
|
||||||
super options
|
|
||||||
@components = options.components or []
|
|
||||||
@world = options.world
|
|
||||||
@level = options.level
|
|
||||||
@callback = options.callback
|
|
||||||
@componentCollection = @supermodel.loadCollection(new ComponentsCollection(), 'components').model
|
|
||||||
|
|
||||||
afterRender: ->
|
|
||||||
super()
|
|
||||||
return unless @supermodel.finished()
|
|
||||||
@buildExtantComponentTreema()
|
|
||||||
@buildAddComponentTreema()
|
|
||||||
|
|
||||||
buildExtantComponentTreema: ->
|
|
||||||
level = new Level()
|
|
||||||
treemaOptions =
|
|
||||||
supermodel: @supermodel
|
|
||||||
schema: level.schema().properties.thangs.items.properties.components
|
|
||||||
data: _.cloneDeep @components
|
|
||||||
callbacks: {select: @onSelectExtantComponent, change: @onChangeExtantComponents}
|
|
||||||
noSortable: true
|
|
||||||
nodeClasses:
|
|
||||||
'thang-components-array': ThangComponentsArrayNode
|
|
||||||
'thang-component': ThangComponentNode
|
|
||||||
|
|
||||||
@extantComponentsTreema = @$el.find('#extant-components-column .treema').treema treemaOptions
|
|
||||||
@extantComponentsTreema.build()
|
|
||||||
@$el.find('#extant-components-column .treema').droppable({
|
|
||||||
drop: =>
|
|
||||||
@onAddComponentEnterPressed @selectedRow
|
|
||||||
})
|
|
||||||
|
|
||||||
buildAddComponentTreema: ->
|
|
||||||
return unless @componentCollection and @extantComponentsTreema
|
|
||||||
extantComponents = @extantComponentsTreema.data
|
|
||||||
componentsUsedCount = extantComponents.length
|
|
||||||
return if @lastComponentsUsedCount is componentsUsedCount
|
|
||||||
@lastComponentsUsedCount = componentsUsedCount
|
|
||||||
components = (m.attributes for m in @componentCollection.models)
|
|
||||||
_.remove components, (comp) =>
|
|
||||||
_.find extantComponents, {original: comp.original} # already have this one added
|
|
||||||
components = _.sortBy components, (comp) -> comp.system + '.' + comp.name
|
|
||||||
|
|
||||||
treemaOptions =
|
|
||||||
supermodel: @supermodel
|
|
||||||
schema: {type: 'array', items: LevelComponent.schema}
|
|
||||||
data: ($.extend(true, {}, c) for c in components)
|
|
||||||
callbacks: {
|
|
||||||
select: @onSelectAddableComponent
|
|
||||||
enter: @onAddComponentEnterPressed
|
|
||||||
dblclick: @onAddComponentDoubleClicked
|
|
||||||
mouseenter: @onAddComponentMouseEnter
|
|
||||||
mouseleave: @onAddComponentMouseLeave
|
|
||||||
}
|
|
||||||
readOnly: true
|
|
||||||
noSortable: true
|
|
||||||
nodeClasses:
|
|
||||||
'array': ComponentArrayNode
|
|
||||||
'object': ComponentNode
|
|
||||||
# I have no idea why it's not building in the Thang Editor unless I defer
|
|
||||||
_.defer (=>
|
|
||||||
@addComponentsTreema = @$el.find('#add-component-column .treema').treema treemaOptions
|
|
||||||
@addComponentsTreema.build()
|
|
||||||
@$el.find('#add-component-column .treema-node').draggable({
|
|
||||||
revert: 'invalid'
|
|
||||||
helper: 'clone'
|
|
||||||
appendTo: 'body'
|
|
||||||
start: (e) ->
|
|
||||||
# Hack to ensure dragged treema node is selected
|
|
||||||
$(@).trigger('click') unless $(@).hasClass 'treema-selected'
|
|
||||||
})
|
|
||||||
@hideLoading()
|
|
||||||
), 500
|
|
||||||
|
|
||||||
onSelectAddableComponent: (e, selected) =>
|
|
||||||
@extantComponentsTreema.deselectAll()
|
|
||||||
@onComponentSelected(selected, false)
|
|
||||||
|
|
||||||
onSelectExtantComponent: (e, selected) =>
|
|
||||||
return if @updatingFromConfig
|
|
||||||
@addComponentsTreema.deselectAll()
|
|
||||||
@onComponentSelected(selected, true)
|
|
||||||
|
|
||||||
onComponentSelected: (selected, extant=true) ->
|
|
||||||
return if @alreadySaving # handle infinite loops
|
|
||||||
@alreadySaving = true
|
|
||||||
@closeExistingView()
|
|
||||||
@alreadySaving = false
|
|
||||||
|
|
||||||
return unless selected.length
|
|
||||||
|
|
||||||
# select dependencies.
|
|
||||||
node = selected[0]
|
|
||||||
original = node.data.original
|
|
||||||
|
|
||||||
toRemoveTreema = []
|
|
||||||
dependent_class = 'treema-dependent'
|
|
||||||
try
|
|
||||||
for index, child of @extantComponentsTreema.childrenTreemas
|
|
||||||
$(child.$el).removeClass(dependent_class)
|
|
||||||
|
|
||||||
for index, child of @extantComponentsTreema.childrenTreemas
|
|
||||||
if child.data.original == original # Here we assume that the treemas are sorted by their dependency.
|
|
||||||
break
|
|
||||||
|
|
||||||
dep_originals = (d.original for d in child.component.attributes.dependencies)
|
|
||||||
for dep_original in dep_originals
|
|
||||||
if original == dep_original
|
|
||||||
toRemoveTreema.push child
|
|
||||||
|
|
||||||
for dep_treema in toRemoveTreema
|
|
||||||
dep_treema.toggleSelect()
|
|
||||||
$(dep_treema.$el).addClass(dependent_class)
|
|
||||||
|
|
||||||
catch error
|
|
||||||
console.error error
|
|
||||||
|
|
||||||
return unless selected.length
|
|
||||||
row = selected[0]
|
|
||||||
@selectedRow = row
|
|
||||||
component = row.component?.attributes or row.data
|
|
||||||
config = if extant then row.data?.config else {}
|
|
||||||
@configView = new ComponentConfigView({
|
|
||||||
supermodel: @supermodel
|
|
||||||
level: @level
|
|
||||||
world: @world
|
|
||||||
config: config
|
|
||||||
component: component
|
|
||||||
editing: extant
|
|
||||||
callback: @onComponentConfigChanged
|
|
||||||
})
|
|
||||||
@insertSubView @configView
|
|
||||||
|
|
||||||
closeExistingView: ->
|
|
||||||
return unless @configView
|
|
||||||
data = @configView.data()
|
|
||||||
@selectedRow.set '/config', data if data and @configView.changed and @configView.editing
|
|
||||||
@removeSubView @configView
|
|
||||||
@configView = null
|
|
||||||
|
|
||||||
onComponentConfigChanged: (data) =>
|
|
||||||
@updatingFromConfig = true
|
|
||||||
@selectedRow.set '/config', data if data and @configView.changed and @configView.editing
|
|
||||||
@updatingFromConfig = false
|
|
||||||
|
|
||||||
onChangeExtantComponents: =>
|
|
||||||
@buildAddComponentTreema()
|
|
||||||
@reportChanges()
|
|
||||||
|
|
||||||
onAddComponentEnterPressed: (node) =>
|
|
||||||
if extantSystems
|
|
||||||
extantSystems =
|
|
||||||
(@supermodel.getModelByOriginalAndMajorVersion LevelSystem, sn.original, sn.majorVersion).attributes.name.toLowerCase() for idx, sn of @level.get('systems')
|
|
||||||
requireSystem = node.data.system.toLowerCase()
|
|
||||||
|
|
||||||
if requireSystem not in extantSystems
|
|
||||||
warn_element = 'Component <b>' + node.data.name + '</b> requires system <b>' + requireSystem + '</b> which is currently not specified in this level.'
|
|
||||||
noty({
|
|
||||||
text: warn_element,
|
|
||||||
layout: 'bottomLeft',
|
|
||||||
type: 'warning'
|
|
||||||
})
|
|
||||||
|
|
||||||
id = node.data._id
|
|
||||||
comp = _.find @componentCollection.models, id: id
|
|
||||||
unless comp
|
|
||||||
return console.error 'Couldn\'t find component for id', id, 'out of', @components.models
|
|
||||||
# Add all dependencies, recursively, unless we already have them
|
|
||||||
toAdd = comp.getDependencies(@componentCollection.models)
|
|
||||||
_.remove toAdd, (c1) =>
|
|
||||||
_.find @extantComponentsTreema.data, (c2) ->
|
|
||||||
c2.original is c1.get('original')
|
|
||||||
for c in toAdd.concat [comp]
|
|
||||||
@extantComponentsTreema.insert '/', {
|
|
||||||
original: c.get('original') ? id
|
|
||||||
majorVersion: c.get('version').major ? 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# reselect newly added child treema in the extantComponentsTreema
|
|
||||||
for index, treema of @extantComponentsTreema.childrenTreemas
|
|
||||||
if treema.component.id is id
|
|
||||||
_.defer =>
|
|
||||||
treema.select()
|
|
||||||
@onSelectExtantComponent({}, [treema])
|
|
||||||
return
|
|
||||||
|
|
||||||
onAddComponentDoubleClicked: (e, treema) =>
|
|
||||||
@onAddComponentEnterPressed treema
|
|
||||||
|
|
||||||
onAddComponentMouseEnter: (e, treema) ->
|
|
||||||
treema.$el.find('.add-button').show()
|
|
||||||
|
|
||||||
onAddComponentMouseLeave: (e, treema) ->
|
|
||||||
treema.$el.find('.add-button').hide()
|
|
||||||
return
|
|
||||||
|
|
||||||
reportChanges: ->
|
|
||||||
@callback?($.extend(true, [], @extantComponentsTreema.data))
|
|
||||||
|
|
||||||
undo: ->
|
|
||||||
if @configView is null or @configView?.editing is false then @extantComponentsTreema.undo() else @configView.undo()
|
|
||||||
|
|
||||||
redo: ->
|
|
||||||
if @configView is null or @configView?.editing is false then @extantComponentsTreema.redo() else @configView.redo()
|
|
||||||
|
|
||||||
class ThangComponentsArrayNode extends TreemaArrayNode
|
|
||||||
valueClass: 'treema-thang-components-array'
|
|
||||||
editable: false
|
|
||||||
sort: true
|
|
||||||
canAddChild: -> false
|
|
||||||
|
|
||||||
sortFunction: (a, b) =>
|
|
||||||
a = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, a.original, a.majorVersion)
|
|
||||||
b = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, b.original, b.majorVersion)
|
|
||||||
return 1 if a.attributes.system > b.attributes.system
|
|
||||||
return -1 if a.attributes.system < b.attributes.system
|
|
||||||
return 1 if a.name > b.name
|
|
||||||
return -1 if a.name < b.name
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class ThangComponentNode extends TreemaObjectNode
|
|
||||||
valueClass: 'treema-thang-component'
|
|
||||||
collection: false
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super(arguments...)
|
|
||||||
@grabDBComponent()
|
|
||||||
|
|
||||||
grabDBComponent: ->
|
|
||||||
@component = @settings.supermodel.getModelByOriginalAndMajorVersion LevelComponent, @data.original, @data.majorVersion
|
|
||||||
console.error 'Couldn\'t find comp for', @data.original, @data.majorVersion, 'from models', @settings.supermodel.models unless @component
|
|
||||||
|
|
||||||
buildValueForDisplay: (valEl) ->
|
|
||||||
return super valEl unless @data.original and @component
|
|
||||||
s = @component.get('system') + '.' + @component.get('name')
|
|
||||||
@buildValueForDisplaySimply valEl, s
|
|
||||||
|
|
||||||
class ComponentArrayNode extends TreemaArrayNode
|
|
||||||
editable: false
|
|
||||||
sort: true
|
|
||||||
canAddChild: -> false
|
|
||||||
|
|
||||||
sortFunction: (a, b) =>
|
|
||||||
return 1 if a.system > b.system
|
|
||||||
return -1 if a.system < b.system
|
|
||||||
return 1 if a.name > b.name
|
|
||||||
return -1 if a.name < b.name
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class ComponentNode extends TreemaObjectNode
|
|
||||||
valueClass: 'treema-component'
|
|
||||||
addButtonTemplate: '<button type="button" class="add-button btn btn-default btn-xs"><span class="glyphicon glyphicon-plus"></span></button>'
|
|
||||||
collection: false
|
|
||||||
|
|
||||||
build: ->
|
|
||||||
super()
|
|
||||||
@$el.find('> .treema-row').append @addButtonTemplate
|
|
||||||
addButton = @$el.find('.add-button')
|
|
||||||
addButton.hide()
|
|
||||||
addButton.click =>
|
|
||||||
@callbacks.enter?(@)
|
|
||||||
@$el
|
|
||||||
|
|
||||||
buildValueForDisplay: (valEl) ->
|
|
||||||
s = @data.system + '.' + @data.name
|
|
||||||
@buildValueForDisplaySimply valEl, s
|
|
||||||
|
|
||||||
onEnterPressed: (args...) ->
|
|
||||||
super(args...)
|
|
||||||
@callbacks.enter?(@)
|
|
282
app/views/editor/component/ThangComponentsEditView.coffee
Normal file
282
app/views/editor/component/ThangComponentsEditView.coffee
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
CocoView = require 'views/kinds/CocoView'
|
||||||
|
template = require 'templates/editor/components/thang-components-edit-view'
|
||||||
|
|
||||||
|
Level = require 'models/Level'
|
||||||
|
LevelComponent = require 'models/LevelComponent'
|
||||||
|
LevelSystem = require 'models/LevelSystem'
|
||||||
|
ComponentsCollection = require 'collections/ComponentsCollection'
|
||||||
|
ThangComponentConfigView = require './ThangComponentConfigView'
|
||||||
|
|
||||||
|
module.exports = class ThangComponentsEditView extends CocoView
|
||||||
|
id: 'thang-components-edit-view'
|
||||||
|
template: template
|
||||||
|
|
||||||
|
constructor: (options) ->
|
||||||
|
super options
|
||||||
|
@components = options.components or []
|
||||||
|
@components = $.extend true, [], @components # just to be sure
|
||||||
|
@lastComponentLength = @components.length
|
||||||
|
@world = options.world
|
||||||
|
@level = options.level
|
||||||
|
@callback = options.callback # TODO: Switch to 'trigger'
|
||||||
|
@loadComponents(@components)
|
||||||
|
|
||||||
|
loadComponents: (components) ->
|
||||||
|
for componentRef in components
|
||||||
|
levelComponent = new LevelComponent()
|
||||||
|
url = "/db/level.component/#{componentRef.original}/version/#{componentRef.majorVersion}"
|
||||||
|
levelComponent.setURL(url)
|
||||||
|
resource = @supermodel.loadModel levelComponent, 'component'
|
||||||
|
@listenToOnce resource, 'loaded', ->
|
||||||
|
return if @handlingChange
|
||||||
|
if @supermodel.finished()
|
||||||
|
@handlingChange = true
|
||||||
|
@onComponentsAdded()
|
||||||
|
@handlingChange = false
|
||||||
|
|
||||||
|
afterRender: ->
|
||||||
|
super()
|
||||||
|
return unless @supermodel.finished()
|
||||||
|
@buildExtantComponentsTreema()
|
||||||
|
@addThangComponentConfigViews()
|
||||||
|
|
||||||
|
buildExtantComponentsTreema: ->
|
||||||
|
treemaOptions =
|
||||||
|
supermodel: @supermodel
|
||||||
|
schema: Level.schema.properties.thangs.items.properties.components
|
||||||
|
data: $.extend true, [], @components
|
||||||
|
callbacks: {select: @onSelectComponent, change: @onComponentsTreemaChanged}
|
||||||
|
noSortable: true
|
||||||
|
nodeClasses:
|
||||||
|
'thang-components-array': ThangComponentsArrayNode
|
||||||
|
|
||||||
|
@extantComponentsTreema = @$el.find('#extant-components-column .treema').treema treemaOptions
|
||||||
|
@extantComponentsTreema.build()
|
||||||
|
|
||||||
|
onComponentsTreemaChanged: =>
|
||||||
|
return if @handlingChange
|
||||||
|
@handlingChange = true
|
||||||
|
componentMap = {}
|
||||||
|
for component in @components
|
||||||
|
componentMap[component.original] = component
|
||||||
|
|
||||||
|
newComponentsList = []
|
||||||
|
for component in @extantComponentsTreema.data
|
||||||
|
newComponentsList.push(componentMap[component.original] or component)
|
||||||
|
@components = newComponentsList
|
||||||
|
|
||||||
|
# update the components list here
|
||||||
|
@onComponentsChanged()
|
||||||
|
@handlingChange = false
|
||||||
|
|
||||||
|
onComponentsChanged: =>
|
||||||
|
# happens whenever the list of components changed, one way or another
|
||||||
|
# * if the treema gets changed
|
||||||
|
# * if components are added externally, like by a modal
|
||||||
|
# * if a dependency loads and is added to the list
|
||||||
|
|
||||||
|
# TODO: Disallow editing components in the list, otherwise this system breaks.
|
||||||
|
|
||||||
|
if @components.length < @lastComponentLength
|
||||||
|
@onComponentsRemoved()
|
||||||
|
else
|
||||||
|
@onComponentsAdded()
|
||||||
|
|
||||||
|
@lastComponentLength = @components.length
|
||||||
|
|
||||||
|
onComponentsRemoved: ->
|
||||||
|
componentMap = {}
|
||||||
|
for component in @components
|
||||||
|
componentMap[component.original] = component
|
||||||
|
|
||||||
|
# Deleting components missing dependencies.
|
||||||
|
while true
|
||||||
|
removedSomething = false
|
||||||
|
for componentRef in _.values(componentMap)
|
||||||
|
componentModel = @supermodel.getModelByOriginalAndMajorVersion(
|
||||||
|
LevelComponent, componentRef.original, componentRef.majorVersion)
|
||||||
|
for dependency in componentModel.get('dependencies') or []
|
||||||
|
if not componentMap[dependency.original]
|
||||||
|
delete componentMap[componentRef.original]
|
||||||
|
component = @supermodel.getModelByOriginal(
|
||||||
|
LevelComponent, componentRef.original)
|
||||||
|
noty {
|
||||||
|
text: "Removed dependent component: #{component.get('name')}"
|
||||||
|
layout: 'topCenter'
|
||||||
|
timeout: 5000
|
||||||
|
type: 'information'
|
||||||
|
}
|
||||||
|
removedSomething = true
|
||||||
|
break if removedSomething
|
||||||
|
break unless removedSomething
|
||||||
|
|
||||||
|
@components = _.values(componentMap)
|
||||||
|
|
||||||
|
# Delete individual component config views that are no longer included.
|
||||||
|
for subview in _.values(@subviews)
|
||||||
|
continue unless subview instanceof ThangComponentConfigView
|
||||||
|
if not componentMap[subview.component.get('original')]
|
||||||
|
@removeSubView(subview)
|
||||||
|
|
||||||
|
@updateComponentsList()
|
||||||
|
@reportChanges()
|
||||||
|
|
||||||
|
updateComponentsList: ->
|
||||||
|
@extantComponentsTreema?.set('/', $.extend(true, [], @components))
|
||||||
|
|
||||||
|
onComponentsAdded: ->
|
||||||
|
componentMap = {}
|
||||||
|
for component in @components
|
||||||
|
componentMap[component.original] = component
|
||||||
|
|
||||||
|
# Go through the map, adding missing dependencies.
|
||||||
|
while true
|
||||||
|
addedSomething = false
|
||||||
|
for componentRef in _.values(componentMap)
|
||||||
|
componentModel = @supermodel.getModelByOriginalAndMajorVersion(
|
||||||
|
LevelComponent, componentRef.original, componentRef.majorVersion)
|
||||||
|
for dependency in componentModel.get('dependencies') or []
|
||||||
|
if not componentMap[dependency.original]
|
||||||
|
component = @supermodel.getModelByOriginalAndMajorVersion(
|
||||||
|
LevelComponent, dependency.original, dependency.majorVersion)
|
||||||
|
if not component
|
||||||
|
@loadComponents([dependency])
|
||||||
|
# will run onComponentsAdded once more when the model loads
|
||||||
|
else
|
||||||
|
addedSomething = true
|
||||||
|
noty {
|
||||||
|
text: "Added dependency: #{component.get('name')}"
|
||||||
|
layout: 'topCenter'
|
||||||
|
timeout: 5000
|
||||||
|
type: 'information'
|
||||||
|
}
|
||||||
|
componentMap[dependency.original] = dependency
|
||||||
|
@components.push dependency
|
||||||
|
break unless addedSomething
|
||||||
|
|
||||||
|
|
||||||
|
# Sort the component list, reorder the component config views
|
||||||
|
@updateComponentsList()
|
||||||
|
@addThangComponentConfigViews()
|
||||||
|
@reportChanges()
|
||||||
|
|
||||||
|
addThangComponentConfigViews: ->
|
||||||
|
# Detach all component config views temporarily.
|
||||||
|
componentConfigViews = {}
|
||||||
|
for subview in _.values(@subviews)
|
||||||
|
continue unless subview instanceof ThangComponentConfigView
|
||||||
|
componentConfigViews[subview.component.get('original')] = subview
|
||||||
|
subview.$el.detach()
|
||||||
|
|
||||||
|
# Put back config views into the DOM based on the component list ordering,
|
||||||
|
# adding and registering new ones as needed.
|
||||||
|
configsEl = @$el.find('#thang-component-configs')
|
||||||
|
for componentRef in @extantComponentsTreema.data
|
||||||
|
subview = componentConfigViews[componentRef.original]
|
||||||
|
if not subview
|
||||||
|
subview = @makeThangComponentConfigView(componentRef)
|
||||||
|
continue unless subview
|
||||||
|
@registerSubView(subview)
|
||||||
|
configsEl.append(subview.$el)
|
||||||
|
|
||||||
|
makeThangComponentConfigView: (thangComponent) ->
|
||||||
|
component = @supermodel.getModelByOriginal(LevelComponent, thangComponent.original)
|
||||||
|
return unless component
|
||||||
|
config = thangComponent.config ? {}
|
||||||
|
configView = new ThangComponentConfigView({
|
||||||
|
supermodel: @supermodel
|
||||||
|
level: @level
|
||||||
|
world: @world
|
||||||
|
config: config
|
||||||
|
component: component
|
||||||
|
})
|
||||||
|
configView.render()
|
||||||
|
@listenTo configView, 'changed', @onConfigChanged
|
||||||
|
configView
|
||||||
|
|
||||||
|
onConfigChanged: (e) ->
|
||||||
|
for thangComponent in @components
|
||||||
|
if thangComponent.original is e.component.get('original')
|
||||||
|
thangComponent.config = e.config
|
||||||
|
@reportChanges()
|
||||||
|
|
||||||
|
onSelectComponent: (e, nodes) =>
|
||||||
|
@extantComponentsTreema.$el.find('.dependent').removeClass('dependent')
|
||||||
|
return unless nodes.length is 1
|
||||||
|
|
||||||
|
# find dependent components
|
||||||
|
dependents = {}
|
||||||
|
dependents[nodes[0].data.original] = true
|
||||||
|
componentsToCheck = [nodes[0].data.original]
|
||||||
|
while componentsToCheck.length
|
||||||
|
componentOriginal = componentsToCheck.pop()
|
||||||
|
for otherComponentRef in @components
|
||||||
|
continue if otherComponentRef.original is componentOriginal
|
||||||
|
continue if dependents[otherComponentRef.original]
|
||||||
|
otherComponent = @supermodel.getModelByOriginal(LevelComponent, otherComponentRef.original)
|
||||||
|
for dependency in otherComponent.get('dependencies')
|
||||||
|
if dependents[dependency.original]
|
||||||
|
dependents[otherComponentRef.original] = true
|
||||||
|
componentsToCheck.push otherComponentRef.original
|
||||||
|
|
||||||
|
# highlight them
|
||||||
|
for child in _.values(@extantComponentsTreema.childrenTreemas)
|
||||||
|
if dependents[child.data.original]
|
||||||
|
child.$el.addClass('dependent')
|
||||||
|
|
||||||
|
# scroll to the config
|
||||||
|
for subview in _.values(@subviews)
|
||||||
|
continue unless subview instanceof ThangComponentConfigView
|
||||||
|
if subview.component.get('original') is nodes[0].data.original
|
||||||
|
subview.$el[0].scrollIntoView()
|
||||||
|
break
|
||||||
|
|
||||||
|
onComponentConfigChanged: (data) =>
|
||||||
|
@updatingFromConfig = true
|
||||||
|
@selectedRow.set '/config', data if data and @configView.changed and @configView.editing
|
||||||
|
@updatingFromConfig = false
|
||||||
|
|
||||||
|
onChangeExtantComponents: =>
|
||||||
|
@buildAddComponentTreema()
|
||||||
|
@reportChanges()
|
||||||
|
|
||||||
|
onAddComponentEnterPressed: (node) =>
|
||||||
|
# TODO: Incorporate this logic when adding components
|
||||||
|
if extantSystems
|
||||||
|
extantSystems =
|
||||||
|
(@supermodel.getModelByOriginalAndMajorVersion LevelSystem, sn.original, sn.majorVersion).attributes.name.toLowerCase() for idx, sn of @level.get('systems')
|
||||||
|
requireSystem = node.data.system.toLowerCase()
|
||||||
|
|
||||||
|
if requireSystem not in extantSystems
|
||||||
|
warn_element = 'Component <b>' + node.data.name + '</b> requires system <b>' + requireSystem + '</b> which is currently not specified in this level.'
|
||||||
|
noty({
|
||||||
|
text: warn_element,
|
||||||
|
layout: 'bottomLeft',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
|
||||||
|
reportChanges: ->
|
||||||
|
@callback?($.extend(true, [], @components))
|
||||||
|
|
||||||
|
# TODO: Fix these.
|
||||||
|
undo: ->
|
||||||
|
if @configView is null or @configView?.editing is false then @extantComponentsTreema.undo() else @configView.undo()
|
||||||
|
|
||||||
|
redo: ->
|
||||||
|
if @configView is null or @configView?.editing is false then @extantComponentsTreema.redo() else @configView.redo()
|
||||||
|
|
||||||
|
class ThangComponentsArrayNode extends TreemaArrayNode
|
||||||
|
valueClass: 'treema-thang-components-array'
|
||||||
|
sort: true
|
||||||
|
|
||||||
|
sortFunction: (a, b) =>
|
||||||
|
a = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, a.original, a.majorVersion)
|
||||||
|
b = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelComponent, b.original, b.majorVersion)
|
||||||
|
return 0 if not (a or b)
|
||||||
|
return 1 if not b
|
||||||
|
return -1 if not a
|
||||||
|
return 1 if a.attributes.system > b.attributes.system
|
||||||
|
return -1 if a.attributes.system < b.attributes.system
|
||||||
|
return 1 if a.name > b.name
|
||||||
|
return -1 if a.name < b.name
|
||||||
|
return 0
|
|
@ -20,6 +20,7 @@ ComponentDocsView = require 'views/docs/ComponentDocumentationView'
|
||||||
|
|
||||||
module.exports = class LevelEditView extends RootView
|
module.exports = class LevelEditView extends RootView
|
||||||
id: 'editor-level-view'
|
id: 'editor-level-view'
|
||||||
|
className: 'editor'
|
||||||
template: template
|
template: template
|
||||||
cache: false
|
cache: false
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
CocoView = require 'views/kinds/CocoView'
|
CocoView = require 'views/kinds/CocoView'
|
||||||
template = require 'templates/editor/level/thang/edit'
|
template = require 'templates/editor/level/thang/edit'
|
||||||
ThangComponentEditView = require 'views/editor/component/ThangComponentEditView'
|
ThangComponentsEditView = require 'views/editor/component/ThangComponentsEditView'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
|
|
||||||
module.exports = class LevelThangEditView extends CocoView
|
module.exports = class LevelThangEditView extends CocoView
|
||||||
###
|
###
|
||||||
In the level editor, is the bar at the top when editing a single thang.
|
In the level editor, is the bar at the top when editing a single thang.
|
||||||
Everything below is part of the ThangComponentEditView, which is shared with the
|
Everything below is part of the ThangComponentsEditView, which is shared with the
|
||||||
ThangType editor view.
|
ThangType editor view.
|
||||||
###
|
###
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ module.exports = class LevelThangEditView extends CocoView
|
||||||
world: @world
|
world: @world
|
||||||
callback: @onComponentsChanged
|
callback: @onComponentsChanged
|
||||||
|
|
||||||
@thangComponentEditView = new ThangComponentEditView options
|
@thangComponentEditView = new ThangComponentsEditView options
|
||||||
@insertSubView @thangComponentEditView
|
@insertSubView @thangComponentEditView
|
||||||
thangTypeNames = (m.get('name') for m in @supermodel.getModels ThangType)
|
thangTypeNames = (m.get('name') for m in @supermodel.getModels ThangType)
|
||||||
input = @$el.find('#thang-type-link input').autocomplete(source: thangTypeNames, minLength: 0, delay: 0, autoFocus: true)
|
input = @$el.find('#thang-type-link input').autocomplete(source: thangTypeNames, minLength: 0, delay: 0, autoFocus: true)
|
||||||
|
|
|
@ -6,17 +6,18 @@ Camera = require 'lib/surface/Camera'
|
||||||
DocumentFiles = require 'collections/DocumentFiles'
|
DocumentFiles = require 'collections/DocumentFiles'
|
||||||
|
|
||||||
RootView = require 'views/kinds/RootView'
|
RootView = require 'views/kinds/RootView'
|
||||||
ThangComponentEditView = require 'views/editor/component/ThangComponentEditView'
|
ThangComponentsEditView = require 'views/editor/component/ThangComponentsEditView'
|
||||||
ThangTypeVersionsModal = require './ThangTypeVersionsModal'
|
ThangTypeVersionsModal = require './ThangTypeVersionsModal'
|
||||||
ThangTypeColorsTabView = require './ThangTypeColorsTabView'
|
ThangTypeColorsTabView = require './ThangTypeColorsTabView'
|
||||||
PatchesView = require 'views/editor/PatchesView'
|
PatchesView = require 'views/editor/PatchesView'
|
||||||
SaveVersionModal = require 'views/modal/SaveVersionModal'
|
SaveVersionModal = require 'views/modal/SaveVersionModal'
|
||||||
template = require 'templates/editor/thang/edit'
|
template = require 'templates/editor/thang/thang-type-edit-view'
|
||||||
|
|
||||||
CENTER = {x: 200, y: 300}
|
CENTER = {x: 200, y: 300}
|
||||||
|
|
||||||
module.exports = class ThangTypeEditView extends RootView
|
module.exports = class ThangTypeEditView extends RootView
|
||||||
id: 'editor-thang-type-edit-view'
|
id: 'thang-type-edit-view'
|
||||||
|
className: 'editor'
|
||||||
template: template
|
template: template
|
||||||
startsLoading: true
|
startsLoading: true
|
||||||
resolution: 4
|
resolution: 4
|
||||||
|
@ -49,7 +50,6 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
@thangType = @supermodel.loadModel(@thangType, 'thang').model
|
@thangType = @supermodel.loadModel(@thangType, 'thang').model
|
||||||
@thangType.saveBackups = true
|
@thangType.saveBackups = true
|
||||||
@listenToOnce @thangType, 'sync', ->
|
@listenToOnce @thangType, 'sync', ->
|
||||||
console.log 'files for?', @thangType.id, @thangType.get 'name'
|
|
||||||
@files = @supermodel.loadCollection(new DocumentFiles(@thangType), 'files').model
|
@files = @supermodel.loadCollection(new DocumentFiles(@thangType), 'files').model
|
||||||
@refreshAnimation = _.debounce @refreshAnimation, 500
|
@refreshAnimation = _.debounce @refreshAnimation, 500
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
components: @thangType.get('components') ? []
|
components: @thangType.get('components') ? []
|
||||||
supermodel: @supermodel
|
supermodel: @supermodel
|
||||||
callback: @onComponentsChanged
|
callback: @onComponentsChanged
|
||||||
@thangComponentEditView = new ThangComponentEditView options
|
@thangComponentEditView = new ThangComponentsEditView options
|
||||||
@insertSubView @thangComponentEditView
|
@insertSubView @thangComponentEditView
|
||||||
|
|
||||||
onComponentsChanged: (components) =>
|
onComponentsChanged: (components) =>
|
||||||
|
|
|
@ -86,6 +86,8 @@ module.exports = class CocoView extends Backbone.View
|
||||||
|
|
||||||
render: ->
|
render: ->
|
||||||
return @ unless me
|
return @ unless me
|
||||||
|
view.destroy() for id, view of @subviews
|
||||||
|
@subviews = {}
|
||||||
super()
|
super()
|
||||||
return @template if _.isString(@template)
|
return @template if _.isString(@template)
|
||||||
@$el.html @template(@getRenderData())
|
@$el.html @template(@getRenderData())
|
||||||
|
@ -248,18 +250,30 @@ module.exports = class CocoView extends Backbone.View
|
||||||
# Subviews
|
# Subviews
|
||||||
|
|
||||||
insertSubView: (view, elToReplace=null) ->
|
insertSubView: (view, elToReplace=null) ->
|
||||||
key = view.id or (view.constructor.name+classCount++)
|
# used to insert views with ids
|
||||||
key = _.string.underscored(key) # handy for autocomplete in dev console
|
key = @makeSubViewKey(view)
|
||||||
@subviews[key].destroy() if key of @subviews
|
@subviews[key].destroy() if key of @subviews
|
||||||
elToReplace ?= @$el.find('#'+view.id)
|
elToReplace ?= @$el.find('#'+view.id)
|
||||||
elToReplace.after(view.el).remove()
|
elToReplace.after(view.el).remove()
|
||||||
view.parent = @
|
@registerSubView(view, key)
|
||||||
view.render()
|
view.render()
|
||||||
view.afterInsert()
|
view.afterInsert()
|
||||||
|
view
|
||||||
|
|
||||||
|
registerSubView: (view, key) ->
|
||||||
|
# used to register views which are custom inserted into the view,
|
||||||
|
# like views where you add multiple instances of them
|
||||||
|
key = @makeSubViewKey(view)
|
||||||
|
view.parent = @
|
||||||
view.parentKey = key
|
view.parentKey = key
|
||||||
@subviews[key] = view
|
@subviews[key] = view
|
||||||
view
|
view
|
||||||
|
|
||||||
|
makeSubViewKey: (view) ->
|
||||||
|
key = view.id or (view.constructor.name+classCount++)
|
||||||
|
key = _.string.underscored(key) # handy for autocomplete in dev console
|
||||||
|
key
|
||||||
|
|
||||||
removeSubView: (view) ->
|
removeSubView: (view) ->
|
||||||
view.$el.empty()
|
view.$el.empty()
|
||||||
delete @subviews[view.parentKey]
|
delete @subviews[view.parentKey]
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
"jsondiffpatch": "~0.1.5",
|
"jsondiffpatch": "~0.1.5",
|
||||||
"nanoscroller": "~0.8.0",
|
"nanoscroller": "~0.8.0",
|
||||||
"jquery.tablesorter": "~2.15.13",
|
"jquery.tablesorter": "~2.15.13",
|
||||||
"treema": "~0.0.9",
|
"treema": "~0.0.12",
|
||||||
"bootstrap": "~3.1.1",
|
"bootstrap": "~3.1.1",
|
||||||
"validated-backbone-mediator": "~0.1.3",
|
"validated-backbone-mediator": "~0.1.3",
|
||||||
"jquery.browser": "~0.0.6",
|
"jquery.browser": "~0.0.6",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
describe 'require', ->
|
describe 'require', ->
|
||||||
it 'has no modules that error when you import them', ->
|
it 'has no modules that error when you import them', ->
|
||||||
modules = window.require.list();
|
modules = window.require.list()
|
||||||
for module in modules
|
for module in modules
|
||||||
try
|
try
|
||||||
require(module)
|
require(module)
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
module.exports.sendTestResponses = (responseMap) ->
|
|
||||||
|
|
Loading…
Reference in a new issue