Skip to content

Commit

Permalink
Merge pull request #407 from CCALI/396-field-types
Browse files Browse the repository at this point in the history
396 field types
  • Loading branch information
tobiasnteireho authored Oct 9, 2024
2 parents efeccc1 + 7cefa85 commit 9a408e6
Show file tree
Hide file tree
Showing 16 changed files with 3,429 additions and 9,682 deletions.
12,777 changes: 3,185 additions & 9,592 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
"grunt-contrib-less": "^2.0.0",
"grunt-run": "^0.8.0",
"grunt-steal": "^1.0.0",
"prettier-standard": "^16.4.1",
"sinon": "^1.17.2",
"standard": "^17.0.0",
"steal": "^2.2.4",
Expand Down
36 changes: 36 additions & 0 deletions src/health-message/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<title>&lt;health-message&gt;</title>
</head>

<body>
<h1 class="text-center">Health-Message Component Demo</h1>
<br />
<h2 class="text-center">alertClass: danger</h2>
<div id="demo-html1" style="margin: 20px;"></div>
<br />
<h2 class="text-center">alertClass: warning</h2>
<div id="demo-html2" style="margin: 20px;"></div>

<script src="../../node_modules/steal/steal.js"
data-main="@empty">
</script>

<script type="steal-module">
import HealthMessage from "~/src/health-message/"
import "~/styles/"
import "~/styles.less"

const HealthMessageComponentDanger = new HealthMessage({viewModel: {message: 'Expected Variable Type (text), found Variable Type (number)', showMessage: true, alertClass: 'danger'}})
const HealthMessageComponentWarning = new HealthMessage({viewModel: {message: 'You have no varriable assigned to the current field', showMessage: true, alertClass: 'warning'}})


const demoHtml1 = document.getElementById('demo-html1')
const demoHtml2 = document.getElementById('demo-html2')

demoHtml1.appendChild(HealthMessageComponentDanger.element)
demoHtml2.appendChild(HealthMessageComponentWarning.element)
</script>
</body>
</html>
15 changes: 15 additions & 0 deletions src/health-message/health-message-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html>

<title>Author App Tests</title>

<div id="mocha"></div>
<div id="test-area"></div>

<script type="text/javascript">
window.less = {async: true, fileSync: true};
</script>

<script src="../../node_modules/steal/steal.js"
mocha="bdd"
main="~/src/health-message/health-message-test.js"></script>
60 changes: 60 additions & 0 deletions src/health-message/health-message-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { HealthMessageVM } from './health-message'
import stache from 'can-stache'
import canViewModel from 'can-view-model'
import { assert } from 'chai'
import $ from 'jquery'

import 'steal-mocha'

describe('<health-message>', () => {
describe('viewModel', () => {
let vm
const testProps = {
showMessage: true,
alertClass: 'danger',
message: 'Danger Zone!'
}

beforeEach(() => {
vm = new HealthMessageVM(testProps)
})

it('passes simple smoke test', () => {
const expectedMessage = 'Danger Zone!'
const expectedAlertClass = 'danger'
const expectedShowMessage = true

assert.equal(vm.message, expectedMessage, 'message should show Danger Zone!')
assert.equal(vm.alertClass, expectedAlertClass, 'alertClass should be danger')
assert.equal(vm.showMessage, expectedShowMessage, 'showMessage should be true')
})
})

describe('Component', () => {
// let vm

afterEach(() => {
document.getElementById('test-area').innerHTML = ''
})

it('shows a warning level message', () => {
const render = (data) => {
const tpl = stache(`
<health-message
showMessage:raw="true"
message:raw="This is a warning message"
alertClass:raw="warning"
/>`)

document.querySelector('#test-area').appendChild(tpl(data))

return canViewModel('health-message')
}

render()

const messageEl = $('health-message')
assert.isTrue(messageEl.is(':visible'), 'should be visible')
})
})
})
2 changes: 1 addition & 1 deletion src/pages-tab/components/page-buttons/page-buttons.stache
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
</select>
</div>
</div>
<var-picker-field appState:from="appState" obj:bind="button" key:from="'repeatVar'" label:from="'Counting Variable:'" />
<var-picker-field appState:from="appState" obj:bind="button" key:from="'repeatVar'" expectedVarType:from="'number'" label:from="'Counting Variable:'" />
</td>
</tr>
{{/for}}
Expand Down
59 changes: 10 additions & 49 deletions src/pages-tab/components/page-fields/page-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export const FieldVM = DefineMap.extend('FieldVM', {
}
},

get expectedVarType () { // Text, Number, MC, TF ...
return pageFieldsHelpers.getExpectedVarType(this.type)
},

get varType () { // Text, Number, MC, TF ...
const varName = this.name.toLowerCase()
const variable = varName && this.vars[varName]
Expand All @@ -41,58 +45,15 @@ export const FieldVM = DefineMap.extend('FieldVM', {
return varType
},

get expectedVarType () { // Text, Number, MC, TF ...
return pageFieldsHelpers.getExpectedVarType(this.type)
},

hasValidTypes: {
value ({ listenTo, resolve }) {
let fieldType = this.type && this.type.toLowerCase()
let varType = this.varType && this.varType.toLowerCase()
let isValid = pageFieldsHelpers.hasValidVarType(fieldType, varType)

listenTo('name', function (name, preName) {
fieldType = this.type && this.type.toLowerCase()
varType = this.varType && this.varType.toLowerCase()
isValid = pageFieldsHelpers.hasValidVarType(fieldType, varType)

resolve(isValid)
})

listenTo('type', function (type, preType) {
fieldType = this.type && this.type.toLowerCase()
varType = this.varType && this.varType.toLowerCase()
isValid = pageFieldsHelpers.hasValidVarType(fieldType, varType)
get message () {
const assignedVarType = this.varType ? this.varType.toLowerCase() : ''
const expectedVarType = this.expectedVarType ? this.expectedVarType.toLowerCase() : ''

resolve(isValid)
})

resolve(isValid)
}
return `Found Variable Type: (${assignedVarType}) but expected Variable Type: (${expectedVarType})`
},

get noVariableAssigned () {
return !this.name
},

get showVarRemovalMessage () {
return !this.noVariableAssigned && !this.hasValidTypes
},

get alertClass () {
return this.noVariableAssigned ? 'warning' : 'danger'
},

get problemMessage () {
if (this.noVariableAssigned) {
return `No Variable Assigned -> Field Type: (${this.field.type}) requires Variable Type: (${this.expectedVarType})`
} else if (!this.hasValidTypes) {
this.field.problem = `Field Type: (${this.field.type}) requires Variable Type: (${this.expectedVarType}), found Variable Type: (${this.varType})`
return this.field.problem
}

this.field.problem = ''
return ''
get showMessage () {
return this.expectedVarType.toLowerCase() !== this.varType
},

types: {
Expand Down
11 changes: 7 additions & 4 deletions src/pages-tab/components/page-fields/page-fields.stache
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,13 @@
</select>
</div>
</div>
{{#not(fieldVM.hasValidTypes)}}
<health-message alertClass:from="fieldVM.alertClass" message:from="fieldVM.problemMessage"></health-message>
{{/not}}
<var-picker-field showVarRemovalMessage:from="fieldVM.showVarRemovalMessage" appState:from="appState" filterText:bind="fieldVM.name" obj:bind="fieldVM.field" key:from="'name'" />
<var-picker-field
appState:from="appState"
filterText:bind="fieldVM.name"
obj:bind="fieldVM.field"
key:from="'name'"
expectedVarType:from="fieldVM.expectedVarType"
/>
{{#if(fieldVM.canDefaultValue)}}
<div class="editspan form-group" name="default">
<label class="control-label">Default Value:</label>
Expand Down
17 changes: 0 additions & 17 deletions src/pages-tab/components/question-info/question-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,6 @@ export const QuestionInfoVM = DefineMap.extend('QuestionInfoVM', {
page: {},
appState: {},
guideFiles: {},
get vars () {
return this.appState.guide.vars
},

get showCountingVariableWarning () {
const repeatVarName = this.page && this.page.repeatVar && this.page.repeatVar.toLowerCase()
return !!repeatVarName && this.vars[repeatVarName].type !== 'Number'
},

get showOuterLoopVariableWarning () {
const outerLoopVarName = this.page && this.page.outerLoopVar && this.page.outerLoopVar.toLowerCase()
return !!outerLoopVarName && this.vars[outerLoopVarName].type !== 'Number'
},

healthMessage: {
default: () => 'Counting Variables require Variable Type (Number)'
},

get ckeText () {
return ckeFactory(this.page, 'text', 'Text:')
Expand Down
21 changes: 13 additions & 8 deletions src/pages-tab/components/question-info/question-info.stache
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,26 @@
</div>

<div class="form-upload" style="padding-bottom: 15px;">
<file-picker appState:from="appState" label:from="'Audio'" obj:from="page" key:from="'textAudioURL'" items:from="guideFiles.media" />
<file-picker
appState:from="appState"
label:from="'Audio'"
obj:from="page"
key:from="'textAudioURL'"
items:from="guideFiles.media" />
</div>

<var-picker-field appState:from="appState" obj:bind="page" key:from="'repeatVar'" label:from="'Counting Variable:'" />
{{#if(showCountingVariableWarning)}}
<health-message alertClass:raw="warning" message:from="healthMessage"></health-message>
{{/if}}
<var-picker-field
appState:from="appState"
obj:bind="page"
key:from="'repeatVar'"
label:from="'Counting Variable:'"
expectedVarType:from="'number'" />

<var-picker-field
appState:from="appState"
obj:bind="page" key:from="'outerLoopVar'"
label:from="'Outer Loop Counting Variable:'"
placeholder:from="'You should only use a variable here for Nested Loops'"
expectedVarType:from="'number'"
/>
{{#if(showOuterLoopVariableWarning)}}
<health-message alertClass:raw="warning" message:from="healthMessage"></health-message>
{{/if}}
</fieldset>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html>

<title>Var Picker Field Tests</title>

<div id="mocha"></div>
<div id="test-area"></div>

<script type="text/javascript">
window.less = {async: true, fileSync: true};
</script>

<script src="../../../../../node_modules/steal/steal.js"
mocha="bdd"
main="a2jauthor/src/pages-tab/components/var-picker/field/var-picker-field-test"></script>
60 changes: 60 additions & 0 deletions src/pages-tab/components/var-picker/field/var-picker-field-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { assert } from 'chai'
import { VarPickerFieldVM } from './var-picker-field'
import AppState from 'a2jauthor/src/models/app-state'

import 'steal-mocha'

// ViewModel unit tests
describe('<VarPickerField>', () => {
describe('viewModel', () => {
const testVar = {
name: 'Test Variable',
type: 'Text'
}
const testField = {
name: 'Test Variable',
type: 'text'
}
const appState = new AppState({ guide: { vars: { 'test variable': testVar } } })
let vm

beforeEach(() => {
vm = new VarPickerFieldVM({ appState })
})

it('showMessage - type mismatch', () => {
vm.obj = testField
vm.key = 'name'
vm.filterText = 'Test Variable'

vm.expectedVarType = 'number'
assert.equal(vm.showMessage, true, 'should return true when health problem found aka types dont match')

vm.expectedVarType = 'text'
assert.equal(vm.showMessage, false, 'should return false/hide message when types match')
})

it('showMessage - unknown variable name', () => {
const originalName = testField.name
testField.name = 'Bad Var'
vm.obj = testField
vm.key = 'name'

const expectedHealthMessage = 'Variable Not Found, please assign a valid Variable Name'
assert.equal(vm.showMessage, true, 'should return true when unknown variable found ex: typo')
assert.equal(vm.message, expectedHealthMessage, 'should show variable not found message')

testField.name = originalName
})

it('message', () => {
vm.obj = testField
vm.key = 'name'
vm.filterText = 'Test Variable'

vm.expectedVarType = 'number'

assert.equal(vm.message, 'Found Variable Type: (text) but expected Variable Type: (number)', 'should return a message describing mixed field/var types')
})
})
})
22 changes: 19 additions & 3 deletions src/pages-tab/components/var-picker/field/var-picker-field.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,26 @@ import template from './var-picker-field.stache'
import { TVariable } from '~/legacy/viewer/A2J_Types'
import { onlyOne } from '../../../helpers/helpers'

export const VarPickerField = DefineMap.extend('VarPickerField', {
export const VarPickerFieldVM = DefineMap.extend('VarPickerFieldVM', {
page: {},
appState: {},
showVarRemovalMessage: {},
expectedVarType: {}, // passed in from parent
get showMessage () {
const assignedVarType = this.assignedVariable ? this.assignedVariable.type.toLowerCase() : ''
const expectedVarType = this.expectedVarType ? this.expectedVarType.toLowerCase() : ''
const validVarName = this.validVarName(this.filterText)

return !validVarName || (assignedVarType !== '' && assignedVarType !== expectedVarType)
},
get message () {
const assignedVarType = this.assignedVariable ? this.assignedVariable.type.toLowerCase() : ''
const expectedVarType = this.expectedVarType ? this.expectedVarType.toLowerCase() : ''
const validVarName = this.validVarName(this.filterText)

return validVarName
? `Found Variable Type: (${assignedVarType}) but expected Variable Type: (${expectedVarType})`
: 'Variable Not Found, please assign a valid Variable Name'
},
// obj[key] like button['name']
obj: {
type: 'any'
Expand Down Expand Up @@ -126,5 +142,5 @@ export default Component.extend({
tag: 'var-picker-field',
view: template,
leakScope: false,
ViewModel: VarPickerField
ViewModel: VarPickerFieldVM
})
Loading

0 comments on commit 9a408e6

Please sign in to comment.