add compatibility stats to mod page
This commit is contained in:
parent
aeca48c419
commit
ba7d6a0e51
|
@ -1,6 +1,7 @@
|
|||
# Release notes
|
||||
## Upcoming
|
||||
* For the web UI:
|
||||
* Added stats to compatibility list.
|
||||
* Fixed compatibility list showing beta header when there's no beta in progress.
|
||||
|
||||
## 2.8.2
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
ViewData["Title"] = "SMAPI mod compatibility";
|
||||
}
|
||||
@section Head {
|
||||
<link rel="stylesheet" href="~/Content/css/mods.css?r=20181109" />
|
||||
<link rel="stylesheet" href="~/Content/css/mods.css?r=20181122" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tablesorter@2.31.0/dist/js/jquery.tablesorter.combined.min.js" crossorigin="anonymous"></script>
|
||||
<script src="~/Content/js/mods.js?r=20181109"></script>
|
||||
<script src="~/Content/js/mods.js?r=20181122"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
var data = @Json.Serialize(Model.Mods, new JsonSerializerSettings { Formatting = Formatting.None });
|
||||
|
@ -36,7 +36,7 @@
|
|||
</div>
|
||||
<div id="filter-area">
|
||||
<input type="checkbox" id="show-advanced" v-model="showAdvanced" />
|
||||
<label for="show-advanced">show detailed options</label>
|
||||
<label for="show-advanced">show advanced info and options</label>
|
||||
<div id="filters" v-show="showAdvanced">
|
||||
<div v-for="(filterGroup, key) in filters">
|
||||
{{key}}: <span v-for="filter in filterGroup" v-bind:class="{ active: filter.value }"><input type="checkbox" v-bind:id="filter.id" v-model="filter.value" v-on:change="applyFilters" /> <label v-bind:for="filter.id">{{filter.label}}</label></span>
|
||||
|
@ -44,7 +44,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mod-count" v-show="showAdvanced">{{visibleCount}} mods shown.</div>
|
||||
<div id="mod-count" v-show="showAdvanced">
|
||||
<span v-if="visibleStats.total > 0">{{visibleStats.total}} mods shown ({{Math.round((visibleStats.compatible + visibleStats.workaround) / visibleStats.total * 100)}}% compatible or have a workaround, {{Math.round((visibleStats.soon + visibleStats.broken) / visibleStats.total * 100)}}% broken, {{Math.round(visibleStats.abandoned / visibleStats.total * 100)}}% obsolete).</span>
|
||||
<span v-else>No matching mods found.</span>
|
||||
</div>
|
||||
<table class="wikitable" id="mod-list">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
@ -4,10 +4,19 @@ var smapi = smapi || {};
|
|||
var app;
|
||||
smapi.modList = function (mods) {
|
||||
// init data
|
||||
var defaultStats = {
|
||||
total: 0,
|
||||
compatible: 0,
|
||||
workaround: 0,
|
||||
soon: 0,
|
||||
broken: 0,
|
||||
abandoned: 0,
|
||||
invalid: 0
|
||||
};
|
||||
var data = {
|
||||
mods: mods,
|
||||
visibleCount: mods.length,
|
||||
showAdvanced: false,
|
||||
visibleStats: $.extend({}, defaultStats),
|
||||
filters: {
|
||||
source: {
|
||||
open: {
|
||||
|
@ -130,27 +139,16 @@ smapi.modList = function (mods) {
|
|||
var words = data.search.toLowerCase().split(" ");
|
||||
|
||||
// apply criteria
|
||||
data.visibleCount = data.mods.length;
|
||||
var stats = data.visibleStats = $.extend({}, defaultStats);
|
||||
for (var i = 0; i < data.mods.length; i++) {
|
||||
var mod = data.mods[i];
|
||||
mod.Visible = true;
|
||||
|
||||
// check filters
|
||||
if (!this.matchesFilters(mod)) {
|
||||
mod.Visible = false;
|
||||
data.visibleCount--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check search terms (all search words should match)
|
||||
if (words.length) {
|
||||
for (var w = 0; w < words.length; w++) {
|
||||
if (mod.SearchableText.indexOf(words[w]) === -1) {
|
||||
mod.Visible = false;
|
||||
data.visibleCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mod.Visible = this.matchesFilters(mod, words);
|
||||
if (mod.Visible) {
|
||||
stats.total++;
|
||||
stats[this.getCompatibilityGroup(mod)]++;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -159,9 +157,10 @@ smapi.modList = function (mods) {
|
|||
/**
|
||||
* Get whether a mod matches the current filters.
|
||||
* @param {object} mod The mod to check.
|
||||
* @param {string[]} searchWords The search words to match.
|
||||
* @returns {bool} Whether the mod matches the filters.
|
||||
*/
|
||||
matchesFilters: function(mod) {
|
||||
matchesFilters: function(mod, searchWords) {
|
||||
var filters = data.filters;
|
||||
|
||||
// check source
|
||||
|
@ -198,8 +197,50 @@ smapi.modList = function (mods) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// check search terms
|
||||
for (var w = 0; w < searchWords.length; w++) {
|
||||
if (mod.SearchableText.indexOf(searchWords[w]) === -1)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a mod's compatibility group for mod metrics.
|
||||
* @param {object} mod The mod to check.
|
||||
* @returns {string} The compatibility group (one of 'compatible', 'workaround', 'soon', 'broken', 'abandoned', or 'invalid').
|
||||
*/
|
||||
getCompatibilityGroup: function (mod) {
|
||||
var status = (mod.BetaCompatibility || mod.Compatibility).Status;
|
||||
switch (status) {
|
||||
// obsolete
|
||||
case "abandoned":
|
||||
case "obsolete":
|
||||
return "abandoned";
|
||||
|
||||
// compatible
|
||||
case "ok":
|
||||
case "optional":
|
||||
return "compatible";
|
||||
|
||||
// workaround
|
||||
case "workaround":
|
||||
case "unofficial":
|
||||
return "workaround";
|
||||
|
||||
// soon/broken
|
||||
case "broken":
|
||||
if (mod.SourceUrl)
|
||||
return "soon";
|
||||
else
|
||||
return "broken";
|
||||
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
app.applyFilters();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue