Added display of plugin Bash Tags and messages.

This commit is contained in:
WrinklyNinja
2014-07-19 10:08:31 +01:00
parent 01c39aa887
commit ced73b2efc
6 changed files with 156 additions and 113 deletions
+5
View File
@@ -290,9 +290,14 @@ li.warn{
}
.tag.add {
color:green;
margin-left: 1.75em;
}
.tag.remove {
color:red;
margin-left: 1.75em;
}
plugin-card > ul {
margin-left: 1.75em;
}
#settings {
+19 -3
View File
@@ -28,16 +28,22 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
onMenuItemClick: {
value: function(evt) {
if (evt.target.id == 'editMetadata') {
} else if (evt.target.id == 'copyMetadata') {
} else if (evt.target.id == 'clearMetadata') {
showMessageDialog('Clear Plugin Metadata', 'Are you sure you want to clear all existing user-added metadata from "' + evt.target.parentElement.parentElement.querySelector('h1').textContent + '"?');
}
}
},
onMenuClick: {
value: function(evt) {
var section = evt.currentTarget.parentElement.parentElement;
section.querySelector('#editMetadata').addEventListener('click', this.onMenuItemClick, false);
section.querySelector('#copyMetadata').addEventListener('click', this.onMenuItemClick, false);
section.querySelector('#clearMetadata').addEventListener('click', this.onMenuItemClick, false);
section.querySelector('#editMetadata').addEventListener('click', section.parentNode.host.onMenuItemClick, false);
section.querySelector('#copyMetadata').addEventListener('click', section.parentNode.host.onMenuItemClick, false);
section.querySelector('#clearMetadata').addEventListener('click', section.parentNode.host.onMenuItemClick, false);
section.querySelector('#menu').classList.toggle('hidden');
}
@@ -61,6 +67,16 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
version.className = 'version';
this.appendChild(version);
var tagAdd = document.createElement('div');
tagAdd.className = 'tag add';
this.appendChild(tagAdd);
var tagRemove = document.createElement('div');
tagRemove.className = 'tag remove';
this.appendChild(tagRemove);
var messages = document.createElement('ul');
this.appendChild(messages);
this.shadowRoot.querySelector('#menuButton').addEventListener('click', this.onMenuClick, false);
}
+61 -49
View File
@@ -34,18 +34,24 @@ function Plugin(obj) {
this.masterlist = obj.masterlist;
this.userlist = obj.userlist;
this.modPriority = obj.modPriority;
this.isGlobalPriority = obj.isGlobalPriority;
this.messages = obj.messages;
this.tags = obj.tags;
this.isDirty = obj.isDirty;
this.id = this.name.replace(/\s+/g, '');
Plugin.prototype.getTagsStrings = function () {
var tagsAdded = [];
var tagsRemoved = [];
if (this.masterlist && this.masterlist.tag) {
for (var i = 0; i < this.masterlist.tag.length; ++i) {
if (this.masterlist.tag[i].name[0] == '-') {
tagsRemoved.push(this.masterlist.tag[i].name);
if (this.tags) {
for (var i = 0; i < this.tags.length; ++i) {
if (this.tags[i].name[0] == '-') {
tagsRemoved.push(this.tags[i].name.substr(1));
} else {
tagsAdded.push(this.masterlist.tag[i].name);
tagsAdded.push(this.tags[i].name);
}
}
}
@@ -53,28 +59,7 @@ function Plugin(obj) {
Prefer the removed list. */
for (var i = 0; i < tagsAdded.length; ++i) {
for (var j = 0; j < tagsRemoved.length; ++j) {
if (tagsRemoved[j].name.toLowerCase() == tagsAdded[i].name.toLowerCase()) {
/* Remove tag from the tagsAdded array. */
tagsAdded.splice(i, 1);
--i;
}
}
}
if (this.userlist && this.userlist.tag) {
for (var i = 0; i < this.userlist.tag.length; ++i) {
if (this.userlist.tag[i][0] == '-') {
tagsRemoved.push(this.userlist.tag[i]);
} else {
tagsAdded.push(this.userlist.tag[i]);
}
}
}
/* Now again make sure that the same tag doesn't appear in both arrays.
Prefer the removed list. */
for (var i = 0; i < tagsAdded.length; ++i) {
for (var j = 0; j < tagsRemoved.length; ++j) {
if (tagsRemoved[j].name.toLowerCase() == tagsAdded[i].name.toLowerCase()) {
if (tagsRemoved[j].toLowerCase() == tagsAdded[i].toLowerCase()) {
/* Remove tag from the tagsAdded array. */
tagsAdded.splice(i, 1);
--i;
@@ -95,40 +80,67 @@ function Plugin(obj) {
this.card = card;
card.id = this.id;
card.querySelector('h1').textContent = this.name;
if (this.crc != '0') {
card.querySelector('.crc').textContent = this.crc;
}
card.querySelector('.version').textContent = this.version;
card.setAttribute('data-active', this.isActive);
card.setAttribute('data-dummy', this.isDummy);
card.setAttribute('data-bsa', this.loadsBSA);
card.setAttribute('data-edits', this.userlist != undefined);
/* Fill in name, version, CRC. */
card.querySelector('h1').textContent = this.name;
card.querySelector('.version').textContent = this.version;
if (this.crc != '0') {
card.querySelector('.crc').textContent = this.crc;
}
/* Fill in Bash Tag suggestions. */
var tags = this.getTagsStrings();
if (tags.tagsAdded) {
card.getElementsByClassName('tag add')[0].textContent = tags.tagsAdded;
} else {
card.getElementsByClassName('tag add')[0].classList.toggle('hidden');
}
if (tags.tagsRemoved) {
card.getElementsByClassName('tag remove')[0].textContent = tags.tagsRemoved;
} else {
card.getElementsByClassName('tag remove')[0].classList.toggle('hidden');
}
/* Fill in messages. */
if (this.messages && this.messages.length != 0) {
this.messages.forEach(function(message) {
var messageLi = document.createElement('li');
messageLi.className = message.type;
// Use the Marked library for Markdown formatting support.
messageLi.innerHTML = marked(message.content[0].str);
card.getElementsByTagName('ul')[0].appendChild(messageLi);
});
} else {
card.getElementsByTagName('ul')[0].classList.toggle('hidden');
}
/* The content elements steal the name, CRC and version, so they
don't get distributed into the editor part of the shadow DOM.
Update the editor elements manually. */
card.shadowRoot.querySelector('#editor h1').textContent = this.name;
card.shadowRoot.querySelector('#editor .version').textContent = this.version;
if (this.crc != '0') {
card.shadowRoot.querySelector('#editor .crc').textContent = this.crc;
}
document.getElementById('main').appendChild(card);
}
Plugin.prototype.getPriorityString = function() {
if (this.userlist) {
var priorityText = 'Priority: ' + this.userlist.modPriority + ', Global: ';
if (this.userlist.isGlobalPriority) {
priorityText += '✓';
} else {
priorityText += '✗';
}
return priorityText;
} else if (this.masterlist) {
var priorityText = 'Priority: ' + this.masterlist.modPriority + ', Global: ';
if (this.masterlist.isGlobalPriority) {
priorityText += '✓';
} else {
priorityText += '✗';
}
return priorityText;
var priorityText = 'Priority: ' + this.modPriority + ', Global: ';
if (this.isGlobalPriority) {
priorityText += '✓';
} else {
return 'Priority: 0, Global: ✗';
priorityText += '✗';
}
return priorityText;
}
Plugin.prototype.createListItem = function() {
+5 -26
View File
@@ -763,42 +763,21 @@ function updateInterfaceWithGameInfo(response) {
++activePluginNo;
}
/*if (plugin.isDirty) {
if (plugin.isDirty) {
++dirtyPluginNo;
}*/
/*
var tags = getTagsStrings(plugin);
if (tags.tagsAdded) {
clone.getElementsByClassName('tag add')[0].textContent = tags.tagsAdded;
} else {
hideElement(clone.getElementsByClassName('tag add')[0]);
}
if (tags.tagsRemoved) {
clone.getElementsByClassName('tag remove')[0].textContent = tags.tagsRemoved;
} else {
hideElement(clone.getElementsByClassName('tag remove')[0]);
}
if (plugin.masterlist && plugin.masterlist.msg && plugin.masterlist.msg.length != 0) {
plugin.masterlist.msg.forEach(function(message) {
var messageLi = document.createElement('li');
messageLi.className = message.type;
// Use the Marked library for Markdown formatting support.
messageLi.innerHTML = marked(message.content[0].str);
clone.getElementsByTagName('ul')[0].appendChild(messageLi);
if (plugin.messages && plugin.messages.length != 0) {
plugin.messages.forEach(function(message) {
if (messageLi.className == 'warn') {
if (message.type == 'warn') {
warnMessageNo++;
} else if (messageLi.className == 'error') {
} else if (message.type == 'error') {
errorMessageNo++;
}
totalMessageNo++;
});
} else {
clone.getElementsByTagName('ul')[0].className += ' hidden';
}
*/
});
document.getElementById('filterTotalMessageNo').textContent = totalMessageNo;
document.getElementById('totalMessageNo').textContent = totalMessageNo;
+2 -2
View File
@@ -182,8 +182,8 @@
</section>
<section id="editor">
<h1></h1>
<div class="crc"></div>
<div class="version"></div>
<span class="version"></span>
<span class="crc"></span>
<input type="checkbox" id="editorEnableEdits">
<label for="editorEnableEdits">Enable Edits</label><br>
<input type="checkbox" id="editorGlobalPriority">
+64 -33
View File
@@ -221,9 +221,9 @@ namespace loot {
// Now store plugin data.
for (const auto& plugin : installed) {
// Test data has 'hasUserEdits', and 'tagsAdd', 'tagsRemove' keys, but
// the first will be handled by userlist lookups, and the other two are probably
// going to get moved around, haven't decided how best to handle the split between masterlist, userlist and plugin-sourced metadata.
/* Each plugin has members while hold its raw masterlist and userlist data for
the editor, and also processed data for the main display.
*/
YAML::Node pluginNode;
pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object.
pluginNode["name"] = plugin.Name();
@@ -239,22 +239,7 @@ namespace loot {
mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(plugin.Name()));
if (!mlistPlugin.HasNameOnly()) {
//Evaluate any conditions
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
try {
mlistPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "\"" << mlistPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % mlistPlugin.Name() % e.what()).str()));
}
//Also check install validity.
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
mlistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
// Now add the masterlist metadata to the pluginNode.
// Now add the masterlist metadata to the pluginNode.]
pluginNode["masterlist"]["modPriority"] = modulo(mlistPlugin.Priority(), max_priority);
pluginNode["masterlist"]["isGlobalPriority"] = (abs(mlistPlugin.Priority()) >= max_priority);
pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter();
@@ -273,20 +258,6 @@ namespace loot {
ulistPlugin.MergeMetadata(g_app_state.CurrentGame().userlist.FindPlugin(plugin.Name()));
if (!ulistPlugin.HasNameOnly()) {
//Evaluate any conditions
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
try {
ulistPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "\"" << ulistPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % ulistPlugin.Name() % e.what()).str()));
}
//Also check install validity.
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
ulistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
// Now add the masterlist metadata to the pluginNode.
pluginNode["userlist"]["modPriority"] = modulo(ulistPlugin.Priority(), max_priority);
@@ -299,6 +270,66 @@ namespace loot {
pluginNode["userlist"]["dirty"] = ulistPlugin.DirtyInfo();
}
// Now merge masterlist and userlist metadata and evaluate,
// putting any resulting metadata into the base of the pluginNode.
mlistPlugin.MergeMetadata(ulistPlugin);
//Evaluate any conditions
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
try {
mlistPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "\"" << mlistPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % mlistPlugin.Name() % e.what()).str()));
}
//Also check install validity.
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
mlistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
// Also evaluate dirty info.
std::list<Message> messages = mlistPlugin.Messages();
std::set<PluginDirtyInfo> dirtyInfo = mlistPlugin.DirtyInfo();
size_t numDirtyInfo(0);
for (const auto &element : dirtyInfo) {
boost::format f;
if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
f = boost::format(boost::locale::translate("Contains %1% ITM records, %2% UDR records and %3% deleted navmeshes. Clean with %4%.")) % element.ITMs() % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
f = boost::format(boost::locale::translate("Clean with %1%.")) % element.CleaningUtility();
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
f = boost::format(boost::locale::translate("Contains %1% UDR records and %2% deleted navmeshes. Clean with %3%.")) % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
f = boost::format(boost::locale::translate("Contains %1% deleted navmeshes. Clean with %2%.")) % element.DeletedNavmeshes() % element.CleaningUtility();
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
f = boost::format(boost::locale::translate("Contains %1% UDR records. Clean with %2%.")) % element.UDRs() % element.CleaningUtility();
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% deleted navmeshes. Clean with %3%.")) % element.ITMs() % element.DeletedNavmeshes() % element.CleaningUtility();
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
f = boost::format(boost::locale::translate("Contains %1% ITM records. Clean with %2%.")) % element.ITMs() % element.CleaningUtility();
else if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% UDR records. Clean with %3%.")) % element.ITMs() % element.UDRs() % element.CleaningUtility();
messages.push_back(loot::Message(loot::Message::warn, f.str()));
++numDirtyInfo;
}
// Now add to pluginNode.
pluginNode["modPriority"] = modulo(mlistPlugin.Priority(), max_priority);
pluginNode["isGlobalPriority"] = (abs(mlistPlugin.Priority()) >= max_priority);
pluginNode["messages"] = messages;
pluginNode["tags"] = mlistPlugin.Tags();
pluginNode["isDirty"] = (numDirtyInfo > 0);
BOOST_LOG_TRIVIAL(trace) << "messages length: " << messages.size();
BOOST_LOG_TRIVIAL(trace) << "tags length: " << mlistPlugin.Tags().size();
gameNode["plugins"].push_back(pluginNode);
}