Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
c243eec6
Commit
c243eec6
authored
Feb 06, 2013
by
cahrens
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move to view file.
parent
08ce212b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
204 additions
and
200 deletions
+204
-200
cms/static/js/models/settings/advanced.js
+4
-200
cms/static/js/views/settings/advanced_view.js
+199
-0
cms/templates/settings.html
+1
-0
No files found.
cms/static/js/models/settings/advanced.js
View file @
c243eec6
...
...
@@ -2,20 +2,15 @@ if (!CMS.Models['Settings']) CMS.Models.Settings = {};
CMS
.
Models
.
Settings
.
Advanced
=
Backbone
.
Model
.
extend
({
defaults
:
{
// the properties are whatever the user types in
// the properties are whatever the user types in
(in addition to whatever comes originally from the server)
},
// which keys to send as the deleted keys on next save
deleteKeys
:
[],
blacklistKeys
:
[],
// an array which the controller should populate directly for now [static not instance based]
initialize
:
function
()
{
console
.
log
(
'in initialize'
);
var
editor
=
ace
.
edit
(
'course-advanced-policy-1-value'
);
editor
.
setTheme
(
"ace/theme/chrome"
);
editor
.
getSession
().
setMode
(
"ace/mode/json"
);
},
validate
:
function
(
attrs
)
{
validate
:
function
(
attrs
)
{
var
errors
=
{};
for
(
key
in
attrs
)
{
for
(
var
key
in
attrs
)
{
if
(
_
.
contains
(
this
.
blacklistKeys
,
key
))
{
errors
[
key
]
=
key
+
" is a reserved keyword or has another editor"
;
}
...
...
@@ -23,194 +18,3 @@ CMS.Models.Settings.Advanced = Backbone.Model.extend({
if
(
!
_
.
isEmpty
(
errors
))
return
errors
;
}
});
if
(
!
CMS
.
Views
[
'Settings'
])
CMS
.
Views
.
Settings
=
{};
CMS
.
Views
.
Settings
.
Advanced
=
CMS
.
Views
.
ValidatingView
.
extend
({
// Model class is CMS.Models.Settings.Advanced
events
:
{
'click .delete-button'
:
"deleteEntry"
,
'click .save-button'
:
"saveView"
,
'click .cancel-button'
:
"revertView"
,
'click .new-button'
:
"addEntry"
,
// update model on changes
'change #course-advanced-policy-key'
:
"updateKey"
,
'change #course-advanced-policy-value'
:
"updateValue"
// TODO enable/disable save (add disabled class) based on validation & dirty
// TODO enable/disable new button?
},
initialize
:
function
()
{
var
self
=
this
;
// instantiates an editor template for each update in the collection
window
.
templateLoader
.
loadRemoteTemplate
(
"advanced_entry"
,
"/static/client_templates/advanced_entry.html"
,
function
(
raw_template
)
{
self
.
template
=
_
.
template
(
raw_template
);
self
.
render
();
}
);
this
.
model
.
on
(
'error'
,
this
.
handleValidationError
,
this
);
},
render
:
function
()
{
// catch potential outside call before template loaded
if
(
!
this
.
template
)
return
this
;
var
listEle$
=
this
.
$el
.
find
(
'.course-advanced-policy-list'
);
listEle$
.
empty
();
// same object so manipulations to one keep the other up to date
this
.
fieldToSelectorMap
=
this
.
selectorToField
=
{};
// iterate through model and produce key : value editors for each property in model.get
var
self
=
this
;
_
.
each
(
_
.
sortBy
(
_
.
keys
(
this
.
model
.
attributes
),
_
.
identity
),
function
(
key
)
{
listEle$
.
append
(
self
.
template
({
key
:
key
,
value
:
self
.
model
.
get
(
key
)}));
self
.
fieldToSelectorMap
[
key
]
=
key
;
});
// insert the empty one
this
.
addEntry
();
// Should this be on an event rather than render?
// var editor = ace.edit('course-advanced-policy-1-value');
// editor.setTheme("ace/theme/monokai");
// editor.getSession().setMode("ace/mode/javascript");
return
this
;
},
deleteEntry
:
function
(
event
)
{
event
.
preventDefault
();
// find out which entry
var
li$
=
$
(
event
.
currentTarget
).
closest
(
'li'
);
// Not data b/c the validation view uses it for a selector
var
key
=
$
(
'.key'
,
li$
).
attr
(
'id'
);
delete
this
.
fieldToSelectorMap
[
key
];
if
(
key
!==
'__new_advanced_key__'
)
{
this
.
model
.
deleteKeys
.
push
(
key
);
delete
this
.
model
[
key
];
}
li$
.
remove
();
},
saveView
:
function
(
event
)
{
// TODO one last verification scan:
// call validateKey on each to ensure proper format
// check for dupes
this
.
model
.
save
({
success
:
function
()
{
window
.
alert
(
"Saved"
);
},
error
:
CMS
.
ServerError
});
// FIXME don't delete if the validation didn't succeed in the save call
// remove deleted attrs
if
(
!
_
.
isEmpty
(
this
.
model
.
deleteKeys
))
{
var
self
=
this
;
// hmmm, not sure how to do this via backbone since we're not destroying the model
$
.
ajax
({
url
:
this
.
model
.
url
,
// json to and fro
contentType
:
"application/json"
,
dataType
:
"json"
,
// delete
type
:
'DELETE'
,
// data
data
:
JSON
.
stringify
({
deleteKeys
:
this
.
model
.
deleteKeys
})
})
.
fail
(
function
(
hdr
,
status
,
error
)
{
CMS
.
ServerError
(
self
.
model
,
"Deleting keys:"
+
status
);
})
.
done
(
function
(
data
,
status
,
error
)
{
// clear deleteKeys on success
self
.
model
.
deleteKeys
=
[];
});
}
},
revertView
:
function
(
event
)
{
this
.
model
.
deleteKeys
=
[];
var
self
=
this
;
this
.
model
.
clear
({
silent
:
true
});
this
.
model
.
fetch
({
success
:
function
()
{
self
.
render
();
},
error
:
CMS
.
ServerError
});
},
addEntry
:
function
()
{
var
listEle$
=
this
.
$el
.
find
(
'.course-advanced-policy-list'
);
listEle$
.
append
(
this
.
template
({
key
:
""
,
value
:
""
}));
// disable the value entry until there's an acceptable key
listEle$
.
find
(
'.course-advanced-policy-value'
).
addClass
(
'disabled'
);
this
.
fieldToSelectorMap
[
'__new_advanced_key__'
]
=
'__new_advanced_key__'
;
},
updateKey
:
function
(
event
)
{
// old key: either the key as in the model or __new_advanced_key__. That is, it doesn't change as the val changes until val is accepted
var
oldKey
=
$
(
event
.
currentTarget
).
closest
(
'.key'
).
attr
(
'id'
);
var
newKey
=
$
(
event
.
currentTarget
).
val
();
console
.
log
(
'update '
,
oldKey
,
newKey
);
// REMOVE ME
if
(
oldKey
!==
newKey
)
{
// may erase other errors but difficult to just remove these
this
.
clearValidationErrors
();
if
(
!
this
.
validateKey
(
oldKey
,
newKey
))
return
;
if
(
this
.
model
.
has
(
newKey
))
{
console
.
log
(
'dupe key'
);
var
error
=
{};
error
[
oldKey
]
=
newKey
+
" has another entry"
;
error
[
newKey
]
=
"Other entry for "
+
newKey
;
this
.
model
.
trigger
(
"error"
,
this
.
model
,
error
);
return
false
;
}
// explicitly call validate to determine whether to proceed (relying on triggered error means putting continuation in the success
// method which is uglier I think?)
var
newEntryModel
=
{};
// set the new key's value to the old one's
newEntryModel
[
newKey
]
=
(
oldKey
===
'__new_advanced_key__'
?
''
:
this
.
model
.
get
(
oldKey
));
var
validation
=
this
.
model
.
validate
(
newEntryModel
);
if
(
validation
)
{
console
.
log
(
'reserved key'
);
this
.
model
.
trigger
(
"error"
,
this
.
model
,
validation
);
// abandon update
return
;
}
// Now safe to actually do the update
this
.
model
.
set
(
newEntryModel
);
delete
this
.
fieldToSelectorMap
[
oldKey
];
if
(
oldKey
!==
'__new_advanced_key__'
)
{
// mark the old key for deletion and delete from field maps
this
.
model
.
deleteKeys
.
push
(
oldKey
);
this
.
model
.
unset
(
oldKey
)
;
}
else
{
// enable the value entry
this
.
$el
.
find
(
'.course-advanced-policy-value'
).
removeClass
(
'disabled'
);
}
// update gui (sets all the ids etc)
$
(
event
.
currentTarget
).
closest
(
'li'
).
replaceWith
(
this
.
template
({
key
:
newKey
,
value
:
this
.
model
.
get
(
newKey
)
}));
this
.
fieldToSelectorMap
[
newKey
]
=
newKey
;
}
},
validateKey
:
function
(
oldKey
,
newKey
)
{
// model validation can't handle malformed keys nor notice if 2 fields have same key; so, need to add that chk here
// TODO ensure there's no spaces or illegal chars
if
(
_
.
isEmpty
(
newKey
))
{
console
.
log
(
'no key'
);
var
error
=
{};
error
[
oldKey
]
=
"Key cannot be an empty string"
;
this
.
model
.
trigger
(
"error"
,
this
.
model
,
error
);
return
false
;
}
else
return
true
;
},
updateValue
:
function
(
event
)
{
// much simpler than key munging. just update the value
var
key
=
$
(
event
.
currentTarget
).
closest
(
'.row'
).
children
(
'.key'
).
attr
(
'id'
);
var
value
=
$
(
event
.
currentTarget
).
val
();
console
.
log
(
'updating '
,
key
,
value
);
this
.
model
.
set
(
key
,
value
,
{
validate
:
true
});
}
});
cms/static/js/views/settings/advanced_view.js
0 → 100644
View file @
c243eec6
if
(
!
CMS
.
Views
[
'Settings'
])
CMS
.
Views
.
Settings
=
{};
CMS
.
Views
.
Settings
.
Advanced
=
CMS
.
Views
.
ValidatingView
.
extend
({
// the key for a newly added policy-- before the user has entered a key value
new_key
:
"__new_advanced_key__"
,
// Model class is CMS.Models.Settings.Advanced
events
:
{
'click .delete-button'
:
"deleteEntry"
,
'click .save-button'
:
"saveView"
,
'click .cancel-button'
:
"revertView"
,
'click .new-button'
:
"addEntry"
,
// update model on changes
'change #course-advanced-policy-key'
:
"updateKey"
,
'change #course-advanced-policy-value'
:
"updateValue"
// TODO enable/disable save (add disabled class) based on validation & dirty
// TODO enable/disable new button?
},
initialize
:
function
()
{
var
self
=
this
;
// instantiates an editor template for each update in the collection
window
.
templateLoader
.
loadRemoteTemplate
(
"advanced_entry"
,
"/static/client_templates/advanced_entry.html"
,
function
(
raw_template
)
{
self
.
template
=
_
.
template
(
raw_template
);
self
.
render
();
}
);
this
.
model
.
on
(
'error'
,
this
.
handleValidationError
,
this
);
},
render
:
function
()
{
// catch potential outside call before template loaded
if
(
!
this
.
template
)
return
this
;
var
listEle$
=
this
.
$el
.
find
(
'.course-advanced-policy-list'
);
listEle$
.
empty
();
// In this case, the fieldToSelectorMap (inherited from ValidatingView) use a map
// from the key to itself. Therefore the selectorToField map is the same object.
this
.
fieldToSelectorMap
=
this
.
selectorToField
=
{};
// iterate through model and produce key : value editors for each property in model.get
var
self
=
this
;
_
.
each
(
_
.
sortBy
(
_
.
keys
(
this
.
model
.
attributes
),
_
.
identity
),
function
(
key
)
{
// TODO: working here
var
newEl
=
self
.
template
({
key
:
key
,
value
:
self
.
model
.
get
(
key
)});
listEle$
.
append
(
newEl
);
self
.
fieldToSelectorMap
[
key
]
=
key
;
// var editor = ace.edit('course-advanced-policy-1-value');
// editor.setTheme("ace/theme/chrome");
// editor.getSession().setMode("ace/mode/json");
});
return
this
;
},
deleteEntry
:
function
(
event
)
{
event
.
preventDefault
();
// find out which entry
var
li$
=
$
(
event
.
currentTarget
).
closest
(
'li'
);
// Not data b/c the validation view uses it for a selector
var
key
=
$
(
'.key'
,
li$
).
attr
(
'id'
);
delete
this
.
fieldToSelectorMap
[
key
];
if
(
key
!==
this
.
new_key
)
{
this
.
model
.
deleteKeys
.
push
(
key
);
delete
this
.
model
[
key
];
}
li$
.
remove
();
},
saveView
:
function
(
event
)
{
// TODO one last verification scan:
// call validateKey on each to ensure proper format
// check for dupes
this
.
model
.
save
({},
{
success
:
function
()
{
window
.
alert
(
"Saved"
);
},
error
:
CMS
.
ServerError
});
// FIXME don't delete if the validation didn't succeed in the save call
// remove deleted attrs
if
(
!
_
.
isEmpty
(
this
.
model
.
deleteKeys
))
{
var
self
=
this
;
// not able to do via backbone since we're not destroying the model
$
.
ajax
({
url
:
this
.
model
.
url
,
// json to and fro
contentType
:
"application/json"
,
dataType
:
"json"
,
// delete
type
:
'DELETE'
,
// data
data
:
JSON
.
stringify
({
deleteKeys
:
this
.
model
.
deleteKeys
})
})
.
fail
(
function
(
hdr
,
status
,
error
)
{
CMS
.
ServerError
(
self
.
model
,
"Deleting keys:"
+
status
);
})
.
done
(
function
(
data
,
status
,
error
)
{
// clear deleteKeys on success
self
.
model
.
deleteKeys
=
[];
});
}
},
revertView
:
function
(
event
)
{
this
.
model
.
deleteKeys
=
[];
var
self
=
this
;
this
.
model
.
clear
({
silent
:
true
});
this
.
model
.
fetch
({
success
:
function
()
{
self
.
render
();
},
error
:
CMS
.
ServerError
});
},
addEntry
:
function
()
{
var
listEle$
=
this
.
$el
.
find
(
'.course-advanced-policy-list'
);
listEle$
.
append
(
this
.
template
({
key
:
""
,
value
:
""
}));
// disable the value entry until there's an acceptable key
listEle$
.
find
(
'.course-advanced-policy-value'
).
addClass
(
'disabled'
);
this
.
fieldToSelectorMap
[
this
.
new_key
]
=
this
.
new_key
;
},
updateKey
:
function
(
event
)
{
// old key: either the key as in the model or new_key.
// That is, it doesn't change as the val changes until val is accepted.
var
oldKey
=
$
(
event
.
currentTarget
).
closest
(
'.key'
).
attr
(
'id'
);
var
newKey
=
$
(
event
.
currentTarget
).
val
();
console
.
log
(
'update '
,
oldKey
,
newKey
);
// TODO: REMOVE ME
if
(
oldKey
!==
newKey
)
{
// may erase other errors but difficult to just remove these
this
.
clearValidationErrors
();
if
(
!
this
.
validateKey
(
oldKey
,
newKey
))
return
;
if
(
this
.
model
.
has
(
newKey
))
{
console
.
log
(
'dupe key'
);
var
error
=
{};
error
[
oldKey
]
=
newKey
+
" has another entry"
;
error
[
newKey
]
=
"Other entry for "
+
newKey
;
this
.
model
.
trigger
(
"error"
,
this
.
model
,
error
);
return
false
;
}
// explicitly call validate to determine whether to proceed (relying on triggered error means putting continuation in the success
// method which is uglier I think?)
var
newEntryModel
=
{};
// set the new key's value to the old one's
newEntryModel
[
newKey
]
=
(
oldKey
===
this
.
new_key
?
''
:
this
.
model
.
get
(
oldKey
));
var
validation
=
this
.
model
.
validate
(
newEntryModel
);
if
(
validation
)
{
console
.
log
(
'reserved key'
);
this
.
model
.
trigger
(
"error"
,
this
.
model
,
validation
);
// abandon update
return
;
}
// Now safe to actually do the update
this
.
model
.
set
(
newEntryModel
);
delete
this
.
fieldToSelectorMap
[
oldKey
];
if
(
oldKey
!==
this
.
new_key
)
{
// mark the old key for deletion and delete from field maps
this
.
model
.
deleteKeys
.
push
(
oldKey
);
this
.
model
.
unset
(
oldKey
)
;
}
else
{
// enable the value entry
this
.
$el
.
find
(
'.course-advanced-policy-value'
).
removeClass
(
'disabled'
);
}
// update gui (sets all the ids etc)
$
(
event
.
currentTarget
).
closest
(
'li'
).
replaceWith
(
this
.
template
({
key
:
newKey
,
value
:
this
.
model
.
get
(
newKey
)
}));
this
.
fieldToSelectorMap
[
newKey
]
=
newKey
;
}
},
validateKey
:
function
(
oldKey
,
newKey
)
{
// model validation can't handle malformed keys nor notice if 2 fields have same key; so, need to add that chk here
// TODO ensure there's no spaces or illegal chars
if
(
_
.
isEmpty
(
newKey
))
{
console
.
log
(
'no key'
);
var
error
=
{};
error
[
oldKey
]
=
"Key cannot be an empty string"
;
this
.
model
.
trigger
(
"error"
,
this
.
model
,
error
);
return
false
;
}
else
return
true
;
},
updateValue
:
function
(
event
)
{
// much simpler than key munging. just update the value
var
key
=
$
(
event
.
currentTarget
).
closest
(
'.row'
).
children
(
'.key'
).
attr
(
'id'
);
var
value
=
$
(
event
.
currentTarget
).
val
();
console
.
log
(
'updating '
,
key
,
value
);
this
.
model
.
set
(
key
,
value
,
{
validate
:
true
});
}
});
\ No newline at end of file
cms/templates/settings.html
View file @
c243eec6
...
...
@@ -23,6 +23,7 @@ from contentstore import utils
<script
type=
"text/javascript"
src=
"${static.url('js/models/settings/course_grading_policy.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/views/settings/main_settings_view.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/models/settings/advanced.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/views/settings/advanced_view.js')}"
></script>
<script
type=
"text/javascript"
>
$
(
document
).
ready
(
function
(){
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment