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
faa97379
Commit
faa97379
authored
Feb 05, 2014
by
polesye
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
BLD-658: Add view for field type Dict in Studio.
parent
fdda638f
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
341 additions
and
60 deletions
+341
-60
CHANGELOG.rst
+5
-0
cms/static/coffee/spec/views/metadata_edit_spec.coffee
+127
-7
cms/static/js/models/metadata.js
+1
-0
cms/static/js/views/metadata.js
+108
-17
cms/static/sass/views/_unit.scss
+73
-5
cms/templates/js/metadata-dict-entry.underscore
+14
-0
cms/templates/widgets/metadata-edit.html
+5
-15
cms/templates/widgets/tabs/metadata-edit-tab.html
+5
-15
common/lib/xmodule/xmodule/x_module.py
+3
-1
No files found.
CHANGELOG.rst
View file @
faa97379
...
@@ -5,6 +5,11 @@ These are notable changes in edx-platform. This is a rolling list of changes,
...
@@ -5,6 +5,11 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
the top. Include a label indicating the component affected.
Blades: Fix for the list metadata editor that gets into a bad state where "Add"
is disabled. BLD-821.
Blades: Add view for field type Dict in Studio. BLD-658.
Blades: Refactor stub implementation of LTI Provider. BLD-601.
Blades: Refactor stub implementation of LTI Provider. BLD-601.
LMS: In left accordion and progress page, due dates are now displayed in time
LMS: In left accordion and progress page, due dates are now displayed in time
...
...
cms/static/coffee/spec/views/metadata_edit_spec.coffee
View file @
faa97379
...
@@ -14,6 +14,7 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
...
@@ -14,6 +14,7 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
stringEntryTemplate
=
readFixtures
(
'metadata-string-entry.underscore'
)
stringEntryTemplate
=
readFixtures
(
'metadata-string-entry.underscore'
)
optionEntryTemplate
=
readFixtures
(
'metadata-option-entry.underscore'
)
optionEntryTemplate
=
readFixtures
(
'metadata-option-entry.underscore'
)
listEntryTemplate
=
readFixtures
(
'metadata-list-entry.underscore'
)
listEntryTemplate
=
readFixtures
(
'metadata-list-entry.underscore'
)
dictEntryTemplate
=
readFixtures
(
'metadata-dict-entry.underscore'
)
beforeEach
->
beforeEach
->
setFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-editor-tpl"
,
type
:
"text/template"
}).
text
(
editorTemplate
))
setFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-editor-tpl"
,
type
:
"text/template"
}).
text
(
editorTemplate
))
...
@@ -21,6 +22,7 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
...
@@ -21,6 +22,7 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-string-entry"
,
type
:
"text/template"
}).
text
(
stringEntryTemplate
))
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-string-entry"
,
type
:
"text/template"
}).
text
(
stringEntryTemplate
))
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-option-entry"
,
type
:
"text/template"
}).
text
(
optionEntryTemplate
))
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-option-entry"
,
type
:
"text/template"
}).
text
(
optionEntryTemplate
))
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-list-entry"
,
type
:
"text/template"
}).
text
(
listEntryTemplate
))
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-list-entry"
,
type
:
"text/template"
}).
text
(
listEntryTemplate
))
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-dict-entry"
,
type
:
"text/template"
}).
text
(
dictEntryTemplate
))
genericEntry
=
{
genericEntry
=
{
default_value
:
'default value'
,
default_value
:
'default value'
,
...
@@ -92,6 +94,24 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
...
@@ -92,6 +94,24 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
value
:
"12:12:12"
value
:
"12:12:12"
}
}
dictEntry
=
{
default_value
:
{
'en'
:
'English'
,
'ru'
:
'Русский'
},
display_name
:
"New Dict"
,
explicitly_set
:
false
,
field_name
:
"dict"
,
help
:
"Specifies the name for this component."
,
type
:
MetadataModel
.
DICT_TYPE
,
value
:
{
'en'
:
'English'
,
'ru'
:
'Русский'
,
'ua'
:
'Українська'
,
'fr'
:
'Français'
}
}
# Test for the editor that creates the individual views.
# Test for the editor that creates the individual views.
describe
"MetadataView.Editor creates editors for each field"
,
->
describe
"MetadataView.Editor creates editors for each field"
,
->
...
@@ -116,17 +136,18 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
...
@@ -116,17 +136,18 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
value
:
null
value
:
null
},
},
listEntry
,
listEntry
,
timeEntry
timeEntry
,
dictEntry
]
]
)
)
it
"creates child views on initialize, and sorts them alphabetically"
,
->
it
"creates child views on initialize, and sorts them alphabetically"
,
->
view
=
new
MetadataView
.
Editor
({
collection
:
@
model
})
view
=
new
MetadataView
.
Editor
({
collection
:
@
model
})
childModels
=
view
.
collection
.
models
childModels
=
view
.
collection
.
models
expect
(
childModels
.
length
).
toBe
(
7
)
expect
(
childModels
.
length
).
toBe
(
8
)
# Be sure to check list view as well as other input types
# Be sure to check list view as well as other input types
childViews
=
view
.
$el
.
find
(
'.setting-input, .list-settings'
)
childViews
=
view
.
$el
.
find
(
'.setting-input, .list-settings'
)
expect
(
childViews
.
length
).
toBe
(
7
)
expect
(
childViews
.
length
).
toBe
(
8
)
verifyEntry
=
(
index
,
display_name
,
type
)
->
verifyEntry
=
(
index
,
display_name
,
type
)
->
expect
(
childModels
[
index
].
get
(
'display_name'
)).
toBe
(
display_name
)
expect
(
childModels
[
index
].
get
(
'display_name'
)).
toBe
(
display_name
)
...
@@ -135,10 +156,11 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
...
@@ -135,10 +156,11 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
verifyEntry
(
0
,
'Display Name'
,
'text'
)
verifyEntry
(
0
,
'Display Name'
,
'text'
)
verifyEntry
(
1
,
'Inputs'
,
'number'
)
verifyEntry
(
1
,
'Inputs'
,
'number'
)
verifyEntry
(
2
,
'List'
,
''
)
verifyEntry
(
2
,
'List'
,
''
)
verifyEntry
(
3
,
'Show Answer'
,
'select-one'
)
verifyEntry
(
3
,
'New Dict'
,
''
)
verifyEntry
(
4
,
'Time'
,
'text'
)
verifyEntry
(
4
,
'Show Answer'
,
'select-one'
)
verifyEntry
(
5
,
'Unknown'
,
'text'
)
verifyEntry
(
5
,
'Time'
,
'text'
)
verifyEntry
(
6
,
'Weight'
,
'number'
)
verifyEntry
(
6
,
'Unknown'
,
'text'
)
verifyEntry
(
7
,
'Weight'
,
'number'
)
it
"returns its display name"
,
->
it
"returns its display name"
,
->
view
=
new
MetadataView
.
Editor
({
collection
:
@
model
})
view
=
new
MetadataView
.
Editor
({
collection
:
@
model
})
...
@@ -351,7 +373,9 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
...
@@ -351,7 +373,9 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
assertCanUpdateView
(
@
listView
,
[
'a new item'
,
'another new item'
,
'a third'
])
assertCanUpdateView
(
@
listView
,
[
'a new item'
,
'another new item'
,
'a third'
])
it
"has a clear method to revert to the model default"
,
->
it
"has a clear method to revert to the model default"
,
->
@
el
.
find
(
'.create-setting'
).
click
()
assertClear
(
@
listView
,
[
'a thing'
,
'another thing'
])
assertClear
(
@
listView
,
[
'a thing'
,
'another thing'
])
expect
(
@
el
.
find
(
'.create-setting'
)).
not
.
toHaveClass
(
'is-disabled'
)
it
"has an update model method"
,
->
it
"has an update model method"
,
->
assertUpdateModel
(
@
listView
,
null
,
[
'a new value'
])
assertUpdateModel
(
@
listView
,
null
,
[
'a new value'
])
...
@@ -486,3 +510,99 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
...
@@ -486,3 +510,99 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
it
"has an update model method"
,
->
it
"has an update model method"
,
->
assertUpdateModel
(
@
view
,
'12:12:12'
,
'23:59:59'
)
assertUpdateModel
(
@
view
,
'12:12:12'
,
'23:59:59'
)
describe
"MetadataView.Dict allows the user to enter key-value pairs of strings"
,
->
beforeEach
->
dictModel
=
new
MetadataModel
(
$
.
extend
(
true
,
{},
dictEntry
))
@
dictView
=
new
MetadataView
.
Dict
({
model
:
dictModel
})
@
el
=
@
dictView
.
$el
main
()
it
"returns the initial value upon initialization"
,
->
assertValueInView
(
@
dictView
,
{
'en'
:
'English'
,
'ru'
:
'Русский'
,
'ua'
:
'Українська'
,
'fr'
:
'Français'
})
it
"updates its value correctly"
,
->
assertCanUpdateView
(
@
dictView
,
{
'ru'
:
'Русский'
,
'ua'
:
'Українська'
,
'fr'
:
'Français'
})
it
"has a clear method to revert to the model default"
,
->
@
el
.
find
(
'.create-setting'
).
click
()
assertClear
(
@
dictView
,
{
'en'
:
'English'
,
'ru'
:
'Русский'
})
expect
(
@
el
.
find
(
'.create-setting'
)).
not
.
toHaveClass
(
'is-disabled'
)
it
"has an update model method"
,
->
assertUpdateModel
(
@
dictView
,
null
,
{
'fr'
:
'Français'
})
it
"can add an entry"
,
->
expect
(
_
.
keys
(
@
dictView
.
model
.
get
(
'value'
)).
length
).
toEqual
(
4
)
@
el
.
find
(
'.create-setting'
).
click
()
expect
(
@
el
.
find
(
'input.input-key'
).
length
).
toEqual
(
5
)
it
"can remove an entry"
,
->
expect
(
_
.
keys
(
@
dictView
.
model
.
get
(
'value'
)).
length
).
toEqual
(
4
)
@
el
.
find
(
'.remove-setting'
).
first
().
click
()
expect
(
_
.
keys
(
@
dictView
.
model
.
get
(
'value'
)).
length
).
toEqual
(
3
)
it
"only allows one blank entry at a time"
,
->
expect
(
@
el
.
find
(
'input.input-key'
).
length
).
toEqual
(
4
)
@
el
.
find
(
'.create-setting'
).
click
()
@
el
.
find
(
'.create-setting'
).
click
()
expect
(
@
el
.
find
(
'input.input-key'
).
length
).
toEqual
(
5
)
it
"only allows unique keys"
,
->
data
=
[
{
expectedValue
:
{
'ru'
:
'Русский'
},
initialValue
:
{
'ru'
:
'Русский'
},
testValue
:
{
'key'
:
'ru'
'value'
:
''
}
},
{
expectedValue
:
{
'ru'
:
'Русский'
},
initialValue
:
{
'ru'
:
'Some value'
},
testValue
:
{
'key'
:
'ru'
'value'
:
'Русский'
}
},
{
expectedValue
:
{
'ru'
:
'Русский'
},
initialValue
:
{
'ru'
:
'Русский'
},
testValue
:
{
'key'
:
''
'value'
:
''
}
}
]
_
.
each
data
,
((
d
,
index
)
->
@
dictView
.
setValueInEditor
(
d
.
initialValue
)
@
dictView
.
updateModel
();
@
el
.
find
(
'.create-setting'
).
click
()
item
=
@
el
.
find
(
'.list-settings-item'
).
last
()
item
.
find
(
'.input-key'
).
val
(
d
.
testValue
.
key
);
item
.
find
(
'.input-value'
).
val
(
d
.
testValue
.
value
);
expect
(
@
dictView
.
getValueFromEditor
()).
toEqual
(
d
.
expectedValue
)
).
bind
(
@
)
it
"re-enables the add setting button after entering a new value"
,
->
expect
(
@
el
.
find
(
'input.input-key'
).
length
).
toEqual
(
4
)
@
el
.
find
(
'.create-setting'
).
click
()
expect
(
@
el
.
find
(
'.create-setting'
)).
toHaveClass
(
'is-disabled'
)
@
el
.
find
(
'input.input-key'
).
last
().
val
(
'third setting'
)
@
el
.
find
(
'input.input-key'
).
last
().
trigger
(
'input'
)
expect
(
@
el
.
find
(
'.create-setting'
)).
not
.
toHaveClass
(
'is-disabled'
)
cms/static/js/models/metadata.js
View file @
faa97379
...
@@ -107,6 +107,7 @@ define(["backbone"], function(Backbone) {
...
@@ -107,6 +107,7 @@ define(["backbone"], function(Backbone) {
Metadata
.
FLOAT_TYPE
=
"Float"
;
Metadata
.
FLOAT_TYPE
=
"Float"
;
Metadata
.
GENERIC_TYPE
=
"Generic"
;
Metadata
.
GENERIC_TYPE
=
"Generic"
;
Metadata
.
LIST_TYPE
=
"List"
;
Metadata
.
LIST_TYPE
=
"List"
;
Metadata
.
DICT_TYPE
=
"Dict"
;
Metadata
.
VIDEO_LIST_TYPE
=
"VideoList"
;
Metadata
.
VIDEO_LIST_TYPE
=
"VideoList"
;
Metadata
.
RELATIVE_TIME_TYPE
=
"RelativeTime"
;
Metadata
.
RELATIVE_TIME_TYPE
=
"RelativeTime"
;
...
...
cms/static/js/views/metadata.js
View file @
faa97379
...
@@ -25,24 +25,21 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
...
@@ -25,24 +25,21 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
var
data
=
{
var
data
=
{
el
:
self
.
$el
.
find
(
'.metadata_entry'
)[
counter
++
],
el
:
self
.
$el
.
find
(
'.metadata_entry'
)[
counter
++
],
model
:
model
model
:
model
};
},
if
(
model
.
getType
()
===
MetadataModel
.
SELECT_TYPE
)
{
conversions
=
{
new
Metadata
.
Option
(
data
);
'Select'
:
'Option'
,
}
'Float'
:
'Number'
,
else
if
(
model
.
getType
()
===
MetadataModel
.
INTEGER_TYPE
||
'Integer'
:
'Number'
model
.
getType
()
===
MetadataModel
.
FLOAT_TYPE
)
{
},
new
Metadata
.
Number
(
data
);
type
=
model
.
getType
();
}
else
if
(
model
.
getType
()
===
MetadataModel
.
LIST_TYPE
)
{
if
(
conversions
[
type
])
{
new
Metadata
.
List
(
data
);
type
=
conversions
[
type
];
}
else
if
(
model
.
getType
()
===
MetadataModel
.
VIDEO_LIST_TYPE
)
{
new
VideoList
(
data
);
}
else
if
(
model
.
getType
()
===
MetadataModel
.
RELATIVE_TIME_TYPE
)
{
new
Metadata
.
RelativeTime
(
data
);
}
}
else
{
if
(
_
.
isFunction
(
Metadata
[
type
]))
{
new
Metadata
[
type
](
data
);
}
else
{
// Everything else is treated as GENERIC_TYPE, which uses String editor.
// Everything else is treated as GENERIC_TYPE, which uses String editor.
new
Metadata
.
String
(
data
);
new
Metadata
.
String
(
data
);
}
}
...
@@ -84,6 +81,8 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
...
@@ -84,6 +81,8 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
}
}
});
});
Metadata
.
VideoList
=
VideoList
;
Metadata
.
String
=
AbstractEditor
.
extend
({
Metadata
.
String
=
AbstractEditor
.
extend
({
events
:
{
events
:
{
...
@@ -277,6 +276,7 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
...
@@ -277,6 +276,7 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
setValueInEditor
:
function
(
value
)
{
setValueInEditor
:
function
(
value
)
{
var
list
=
this
.
$el
.
find
(
'ol'
);
var
list
=
this
.
$el
.
find
(
'ol'
);
list
.
empty
();
list
.
empty
();
_
.
each
(
value
,
function
(
ele
,
index
)
{
_
.
each
(
value
,
function
(
ele
,
index
)
{
var
template
=
_
.
template
(
var
template
=
_
.
template
(
...
@@ -308,6 +308,13 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
...
@@ -308,6 +308,13 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
enableAdd
:
function
()
{
enableAdd
:
function
()
{
this
.
$el
.
find
(
'.create-setting'
).
removeClass
(
'is-disabled'
);
this
.
$el
.
find
(
'.create-setting'
).
removeClass
(
'is-disabled'
);
},
clear
:
function
()
{
AbstractEditor
.
prototype
.
clear
.
apply
(
this
,
arguments
);
if
(
_
.
isNull
(
this
.
model
.
getValue
()))
{
this
.
$el
.
find
(
'.create-setting'
).
removeClass
(
'is-disabled'
);
}
}
}
});
});
...
@@ -386,5 +393,89 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
...
@@ -386,5 +393,89 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList) {
}
}
});
});
Metadata
.
Dict
=
AbstractEditor
.
extend
({
events
:
{
"click .setting-clear"
:
"clear"
,
"keypress .setting-input"
:
"showClearButton"
,
"change input"
:
"updateModel"
,
"input input"
:
"enableAdd"
,
"click .create-setting"
:
"addEntry"
,
"click .remove-setting"
:
"removeEntry"
},
templateName
:
"metadata-dict-entry"
,
getValueFromEditor
:
function
()
{
var
dict
=
{};
_
.
each
(
this
.
$el
.
find
(
'li'
),
function
(
li
,
index
)
{
var
key
=
$
(
li
).
find
(
'.input-key'
).
val
().
trim
(),
value
=
$
(
li
).
find
(
'.input-value'
).
val
().
trim
();
// Keys should be unique, so if our keys are duplicated and
// second key is empty or key and value are empty just do
// nothing. Otherwise, it'll be overwritten by the new value.
if
(
value
===
''
)
{
if
(
key
===
''
||
key
in
dict
)
{
return
false
;
}
}
dict
[
key
]
=
value
;
});
return
dict
;
},
setValueInEditor
:
function
(
value
)
{
var
list
=
this
.
$el
.
find
(
'ol'
),
frag
=
document
.
createDocumentFragment
();
_
.
each
(
value
,
function
(
value
,
key
)
{
var
template
=
_
.
template
(
'<li class="list-settings-item">'
+
'<input type="text" class="input input-key" value="<%= key %>">'
+
'<input type="text" class="input input-value" value="<%= value %>">'
+
'<a href="#" class="remove-action remove-setting" data-value="<%= value %>"><i class="icon-remove-sign"></i><span class="sr">Remove</span></a>'
+
'</li>'
);
frag
.
appendChild
(
$
(
template
({
'key'
:
key
,
'value'
:
value
}))[
0
]);
});
list
.
html
([
frag
]);
},
addEntry
:
function
(
event
)
{
event
.
preventDefault
();
// We don't call updateModel here since it's bound to the
// change event
var
dict
=
$
.
extend
(
true
,
{},
this
.
model
.
get
(
'value'
))
||
{};
dict
[
''
]
=
''
;
this
.
setValueInEditor
(
dict
);
this
.
$el
.
find
(
'.create-setting'
).
addClass
(
'is-disabled'
);
},
removeEntry
:
function
(
event
)
{
event
.
preventDefault
();
var
entry
=
$
(
event
.
currentTarget
).
siblings
(
'.input-key'
).
val
();
this
.
setValueInEditor
(
_
.
omit
(
this
.
model
.
get
(
'value'
),
entry
));
this
.
updateModel
();
this
.
$el
.
find
(
'.create-setting'
).
removeClass
(
'is-disabled'
);
},
enableAdd
:
function
()
{
this
.
$el
.
find
(
'.create-setting'
).
removeClass
(
'is-disabled'
);
},
clear
:
function
()
{
AbstractEditor
.
prototype
.
clear
.
apply
(
this
,
arguments
);
if
(
_
.
isNull
(
this
.
model
.
getValue
()))
{
this
.
$el
.
find
(
'.create-setting'
).
removeClass
(
'is-disabled'
);
}
}
});
return
Metadata
;
return
Metadata
;
});
});
cms/static/sass/views/_unit.scss
View file @
faa97379
...
@@ -619,6 +619,7 @@ body.course.unit,.view-unit {
...
@@ -619,6 +619,7 @@ body.course.unit,.view-unit {
//component-setting-entry
//component-setting-entry
.field.comp-setting-entry
{
.field.comp-setting-entry
{
@include
transition
(
opacity
$tmg-f2
ease-in-out
0s
);
background-color
:
$white
;
background-color
:
$white
;
padding
:
$baseline
;
padding
:
$baseline
;
border-bottom
:
1px
solid
$gray-l2
;
border-bottom
:
1px
solid
$gray-l2
;
...
@@ -640,7 +641,6 @@ body.course.unit,.view-unit {
...
@@ -640,7 +641,6 @@ body.course.unit,.view-unit {
}
}
&
:hover
{
&
:hover
{
@include
transition
(
opacity
$tmg-f2
ease-in-out
0s
);
opacity
:
1
.0
;
opacity
:
1
.0
;
}
}
...
@@ -654,9 +654,7 @@ body.course.unit,.view-unit {
...
@@ -654,9 +654,7 @@ body.course.unit,.view-unit {
}
}
.wrapper-comp-setting
{
.wrapper-comp-setting
{
display
:
inline-block
;
min-width
:
300px
;
min-width
:
300px
;
width
:
55%
;
top
:
0
;
top
:
0
;
vertical-align
:
top
;
vertical-align
:
top
;
margin-bottom
:
5px
;
margin-bottom
:
5px
;
...
@@ -670,7 +668,7 @@ body.course.unit,.view-unit {
...
@@ -670,7 +668,7 @@ body.course.unit,.view-unit {
display
:
inline-block
;
display
:
inline-block
;
position
:
relative
;
position
:
relative
;
left
:
0
;
left
:
0
;
width
:
33
%
;
width
:
25
%
;
min-width
:
100px
;
min-width
:
100px
;
margin-right
:
(
$baseline
/
2
);
margin-right
:
(
$baseline
/
2
);
font-weight
:
600
;
font-weight
:
600
;
...
@@ -774,7 +772,6 @@ body.course.unit,.view-unit {
...
@@ -774,7 +772,6 @@ body.course.unit,.view-unit {
display
:
inline-block
;
display
:
inline-block
;
font-color
:
$gray-l6
;
font-color
:
$gray-l6
;
min-width
:
(
$baseline
*
10
);
min-width
:
(
$baseline
*
10
);
width
:
35%
;
vertical-align
:
top
;
vertical-align
:
top
;
}
}
...
@@ -861,6 +858,77 @@ body.course.unit,.view-unit {
...
@@ -861,6 +858,77 @@ body.course.unit,.view-unit {
}
}
}
}
}
}
// TYPE: Dict
.metadata-dict
{
*
{
@include
box-sizing
(
border-box
);
}
// label
.setting-label
{
vertical-align
:
top
;
margin-top
:
(
$baseline
*.
75
);
}
// inputs and labels
.wrapper-dict-settings
{
width
:
55%
;
display
:
inline-block
;
min-width
:
240px
;
// enumerated fields
.list-settings
{
margin
:
(
$baseline
/
2
)
0
0
;
.list-settings-item
{
margin-bottom
:
(
$baseline
/
2
);
}
// inputs
.input
{
width
:
43%
;
margin-right
:
(
$baseline
/
4
);
vertical-align
:
middle
;
display
:
inline-block
;
&
.input-value
{
margin-right
:
(
$baseline
/
2
);
}
}
}
}
.setting-clear
{
vertical-align
:
top
;
margin
:
(
$baseline
*.
75
)
0
0
0
;
}
.create-setting
{
@extend
%ui-btn-flat-outline
;
@extend
%t-action3
;
display
:
block
;
width
:
88%
;
padding
:
(
$baseline
/
2
);
font-weight
:
600
;
*[
class
^=
"icon-"
]
{
margin-right
:
(
$baseline
/
4
);
}
}
.remove-setting
{
@include
transition
(
color
0
.25s
ease-in-out
);
@include
font-size
(
20
);
display
:
inline-block
;
background
:
transparent
;
color
:
$blue-l3
;
&
:hover
{
color
:
$blue
;
}
}
}
}
}
}
}
}
}
...
...
cms/templates/js/metadata-dict-entry.underscore
0 → 100644
View file @
faa97379
<div class="wrapper-comp-setting metadata-dict">
<label class="label setting-label" for="<%= uniqueId %>"><%= model.get('display_name')%></label>
<div id="<%= uniqueId %>" class="wrapper-dict-settings">
<ol class="list-settings"></ol>
<a href="#" class="create-action create-setting">
<i class="icon-plus"></i><%= gettext("Add") %> <span class="sr"><%= model.get('display_name')%></span>
</a>
</div>
<button class="action setting-clear inactive" type="button" name="setting-clear" value="<%= gettext("Clear") %>" data-tooltip="<%= gettext("Clear") %>">
<i class="icon-undo"></i>
<span class="sr">"<%= gettext("Clear Value") %>"</span>
</button>
</div>
<span class="tip setting-help"><%= model.get('help') %></span>
cms/templates/widgets/metadata-edit.html
View file @
faa97379
...
@@ -13,21 +13,11 @@
...
@@ -13,21 +13,11 @@
<%
static
:
include
path
=
"js/metadata-editor.underscore"
/>
<%
static
:
include
path
=
"js/metadata-editor.underscore"
/>
</script>
</script>
<script
id=
"metadata-number-entry"
type=
"text/template"
>
% for template_name in ["metadata-number-entry", "metadata-string-entry", "metadata-option-entry", "metadata-list-entry", "metadata-dict-entry"]:
<%
static
:
include
path
=
"js/metadata-number-entry.underscore"
/>
<script
id=
"${template_name}"
type=
"text/template"
>
</script>
<%
static
:
include
path
=
"js/${template_name}.underscore"
/>
</script>
<script
id=
"metadata-string-entry"
type=
"text/template"
>
% endfor
<%
static
:
include
path
=
"js/metadata-string-entry.underscore"
/>
</script>
<script
id=
"metadata-option-entry"
type=
"text/template"
>
<%
static
:
include
path
=
"js/metadata-option-entry.underscore"
/>
</script>
<script
id=
"metadata-list-entry"
type=
"text/template"
>
<%
static
:
include
path
=
"js/metadata-list-entry.underscore"
/>
</script>
<
%
showHighLevelSource=
'source_code'
in
editable_metadata_fields
and
editable_metadata_fields
['
source_code
']['
explicitly_set
']
and
enable_latex_compiler
%
>
<
%
showHighLevelSource=
'source_code'
in
editable_metadata_fields
and
editable_metadata_fields
['
source_code
']['
explicitly_set
']
and
enable_latex_compiler
%
>
<
%
metadata_field_copy =
copy.copy(editable_metadata_fields)
%
>
<
%
metadata_field_copy =
copy.copy(editable_metadata_fields)
%
>
...
...
cms/templates/widgets/tabs/metadata-edit-tab.html
View file @
faa97379
...
@@ -8,21 +8,11 @@
...
@@ -8,21 +8,11 @@
<%
static
:
include
path
=
"js/metadata-editor.underscore"
/>
<%
static
:
include
path
=
"js/metadata-editor.underscore"
/>
</script>
</script>
<script
id=
"metadata-number-entry"
type=
"text/template"
>
% for template_name in ["metadata-number-entry", "metadata-string-entry", "metadata-option-entry", "metadata-list-entry", "metadata-dict-entry"]:
<%
static
:
include
path
=
"js/metadata-number-entry.underscore"
/>
<script
id=
"${template_name}"
type=
"text/template"
>
</script>
<%
static
:
include
path
=
"js/${template_name}.underscore"
/>
</script>
<script
id=
"metadata-string-entry"
type=
"text/template"
>
% endfor
<%
static
:
include
path
=
"js/metadata-string-entry.underscore"
/>
</script>
<script
id=
"metadata-option-entry"
type=
"text/template"
>
<%
static
:
include
path
=
"js/metadata-option-entry.underscore"
/>
</script>
<script
id=
"metadata-list-entry"
type=
"text/template"
>
<%
static
:
include
path
=
"js/metadata-list-entry.underscore"
/>
</script>
<div
class=
"wrapper-comp-settings metadata_edit"
id=
"settings-tab"
data-metadata=
'${json.dumps(editable_metadata_fields) | h}'
/>
<div
class=
"wrapper-comp-settings metadata_edit"
id=
"settings-tab"
data-metadata=
'${json.dumps(editable_metadata_fields) | h}'
/>
common/lib/xmodule/xmodule/x_module.py
View file @
faa97379
...
@@ -16,7 +16,7 @@ from webob import Response
...
@@ -16,7 +16,7 @@ from webob import Response
from
webob.multidict
import
MultiDict
from
webob.multidict
import
MultiDict
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.fields
import
Scope
,
Integer
,
Float
,
List
,
XBlockMixin
,
String
from
xblock.fields
import
Scope
,
Integer
,
Float
,
List
,
XBlockMixin
,
String
,
Dict
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
xblock.plugin
import
default_select
from
xblock.plugin
import
default_select
from
xblock.runtime
import
Runtime
from
xblock.runtime
import
Runtime
...
@@ -790,6 +790,8 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
...
@@ -790,6 +790,8 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
editor_type
=
"Float"
editor_type
=
"Float"
elif
isinstance
(
field
,
List
):
elif
isinstance
(
field
,
List
):
editor_type
=
"List"
editor_type
=
"List"
elif
isinstance
(
field
,
Dict
):
editor_type
=
"Dict"
elif
isinstance
(
field
,
RelativeTime
):
elif
isinstance
(
field
,
RelativeTime
):
editor_type
=
"RelativeTime"
editor_type
=
"RelativeTime"
metadata_fields
[
field
.
name
][
'type'
]
=
editor_type
metadata_fields
[
field
.
name
][
'type'
]
=
editor_type
...
...
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