diff --git a/design/reputation abilities.txt b/design/reputation abilities.txt new file mode 100644 index 000000000..62845e072 --- /dev/null +++ b/design/reputation abilities.txt @@ -0,0 +1,35 @@ +Not Banned +Comment on things. Star things. Update user settings/profile page. + +Not restricted +Submit mods. Create notes/reviews. Add tags to mods/mod lists. Mark reviews/notes as helpful. Manage mods they are an author/curator for. Report things. + +10 reputation +Custom Avatar. Create help pages. + +20 reputation +Create new tags. Make curator requests. + +40 reputation +Submit, discuss, and vote on corrections. Auto-approval for notes/reviews. + +80 reputation +Endorse up to 5 other users + +160 reputation +Auto-approval for submitted mods. Upload images for mods that have none. + +320 reputation +Endorse up to 10 other users. Update notes from inactive users. + +640 reputation +Endorse up to 15 other users. + +1280 reputation +Custom user title. 1 free month of premium access. + +2560 reputation +2 free months of premium access + +5120 reputation +Lifetime premium access. \ No newline at end of file diff --git a/mod-picker/app/assets/config/manifest.js b/mod-picker/app/assets/config/manifest.js index 03360a6dc..5d83bae54 100644 --- a/mod-picker/app/assets/config/manifest.js +++ b/mod-picker/app/assets/config/manifest.js @@ -10,33 +10,5 @@ //= link "help/High Hrothgar.css" //= link "landing/High Hrothgar.css" //= link legal.css -// landing page // VENDOR ASSETS -//= link rzslider.min.css -//= link simplemde.min.css -//= link angular.min.1.5.1.js -//= link bindonce.js -//= link marked.min.js -//= link angular-marked.min.js -//= link angular-drag-and-drop-lists.min.js -//= link angular-ui-router.min.js -//= link ct-ui-router-extras.min.js -//= link angular-smooth-scroll.min.js -//= link heartcode-canvasloader-min.js -//= link angular-relative-date.min.js -//= link rzslider.min.js -//= link angular-animate.min.js -//= link angular-elastic-input.min.js -//= link simplemde.min.js -//= link spin.min.js -// TEMPORARY VENDOR ASSETS -//= link animate.css -//= link bootstrap.min.css -//= link bootstrap.min.js -//= link wow.min.js -//= link style-responsive.css -//= link jquery.countdown.min.js -//= link jquery.nicescroll.min.js -//= link jquery.smooth-scroll.js -//= link script.js -//= link logo.png \ No newline at end of file +//= link modpicker-vendor.js \ No newline at end of file diff --git a/mod-picker/app/assets/javascripts/BackendAPI/configFilesService.js b/mod-picker/app/assets/javascripts/BackendAPI/configFilesService.js index 3c271018b..f1f7c39f0 100644 --- a/mod-picker/app/assets/javascripts/BackendAPI/configFilesService.js +++ b/mod-picker/app/assets/javascripts/BackendAPI/configFilesService.js @@ -18,14 +18,17 @@ app.service('configFilesService', function() { }; this.addCustomConfigFile = function(model, customConfigFile) { + customConfigFile.active = true; var foundGroup = model.find(function(group) { return group.name === 'Custom'; }); if (foundGroup) { foundGroup.children.push(customConfigFile); + foundGroup.activeConfig = customConfigFile; } else { var group = { name: 'Custom', + activeConfig: customConfigFile, children: [customConfigFile] }; model.push(group); diff --git a/mod-picker/app/assets/javascripts/BackendAPI/modService.js b/mod-picker/app/assets/javascripts/BackendAPI/modService.js index 42a1d85bc..433eceb42 100644 --- a/mod-picker/app/assets/javascripts/BackendAPI/modService.js +++ b/mod-picker/app/assets/javascripts/BackendAPI/modService.js @@ -226,6 +226,7 @@ app.service('modService', function(backend, $q, pageUtils, objectUtils, contribu _destroy: plugin._destroy, author: plugin.author, filename: plugin.filename, + is_esm: plugin.is_esm, crc_hash: plugin.crc_hash, description: plugin.description, file_size: plugin.file_size, @@ -240,10 +241,7 @@ app.service('modService', function(backend, $q, pageUtils, objectUtils, contribu }; this.sanitizePlugins = function(plugins) { - var sanitizedPlugins = []; - plugins.forEach(function(plugin) { - sanitizedPlugins.push(service.sanitizePlugin(plugin)); - }); + var sanitizedPlugins = plugins.map(service.sanitizePlugin); objectUtils.deleteEmptyProperties(sanitizedPlugins, 1); return sanitizedPlugins; }; @@ -256,8 +254,9 @@ app.service('modService', function(backend, $q, pageUtils, objectUtils, contribu name: option.name, display_name: option.display_name, size: option.size, + md5_hash: option.md5_hash, default: option.default, - is_fomod_option: option.is_fomod_option, + is_installer_option: option.is_fomod_option || option.is_installer_option, plugin_dumps: sanitizedPlugins, asset_paths: option.assets }; diff --git a/mod-picker/app/assets/javascripts/Directives/editMod/modAnalysisManager.js b/mod-picker/app/assets/javascripts/Directives/editMod/modAnalysisManager.js index d7bac1894..b2267c84c 100644 --- a/mod-picker/app/assets/javascripts/Directives/editMod/modAnalysisManager.js +++ b/mod-picker/app/assets/javascripts/Directives/editMod/modAnalysisManager.js @@ -99,18 +99,29 @@ app.controller('modAnalysisManagerController', function($scope, $rootScope, plug option.base_name = option.name.replace(regex, ''); }; - $scope.optionMatches = function(option, oldOption) { - var namesMatch = option.base_name === oldOption.base_name; - var fileSizesMatch = option.size == oldOption.size; - return namesMatch || fileSizesMatch; + $scope.optionNamesMatch = function(option, oldOption) { + return option.name === oldOption.name; + }; + + $scope.optionSizesMatch = function(option, oldOption) { + return option.size == oldOption.size; + }; + + $scope.findOldOption = function(oldOptions, option) { + return oldOptions.find(function(oldOption) { + return $scope.optionNamesMatch(option, oldOption) && + $scope.optionSizesMatch(option, oldOption); + }) || oldOptions.find(function(oldOption) { + return $scope.optionNamesMatch(option, oldOption); + }) || oldOptions.find(function(oldOption) { + return $scope.optionSizesMatch(option, oldOption); + }); }; $scope.loadExistingOption = function(option) { var oldOptions = $scope.mod.mod_options; if (!oldOptions) return; - var oldOption = oldOptions.find(function(oldOption) { - return $scope.optionMatches(option, oldOption); - }); + var oldOption = $scope.findOldOption(oldOptions, option); if (oldOption) { option.id = oldOption.id; option.display_name = angular.copy(oldOption.display_name); @@ -120,7 +131,9 @@ app.controller('modAnalysisManagerController', function($scope, $rootScope, plug $scope.prepareModOption = function(option) { $scope.getBaseName(option); option.display_name = angular.copy(option.base_name); - option.nestedAssets = assetUtils.getNestedAssets(option.assets); + if (option.assets && option.assets.length) { + option.nestedAssets = assetUtils.getNestedAssets(option.assets); + } $scope.loadExistingOption(option); }; diff --git a/mod-picker/app/assets/javascripts/Factories/baseFactory.js b/mod-picker/app/assets/javascripts/Factories/baseFactory.js index 368108a49..1007565cf 100644 --- a/mod-picker/app/assets/javascripts/Factories/baseFactory.js +++ b/mod-picker/app/assets/javascripts/Factories/baseFactory.js @@ -102,7 +102,7 @@ app.service('baseFactory', function() { name: "", size: 0, default: false, - is_fomod_option: false + is_installer_option: false } }, mod_list_mod_options: { diff --git a/mod-picker/app/assets/javascripts/Factories/moderationActionsFactory.js b/mod-picker/app/assets/javascripts/Factories/moderationActionsFactory.js index 506acb48b..23da3782e 100644 --- a/mod-picker/app/assets/javascripts/Factories/moderationActionsFactory.js +++ b/mod-picker/app/assets/javascripts/Factories/moderationActionsFactory.js @@ -1,9 +1,11 @@ app.service('moderationActionsFactory', function(userService) { this.buildActions = function($scope) { + $scope.repCounter = 0; + // functions $scope.addRep = function() { - if ($scope.added && !$scope.subtracted) return; - $scope.added = true; + if ($scope.repCounter > 0) return; + $scope.repCounter += 1; userService.addRep($scope.user.id).then(function() { $scope.$emit("successMessage", "Increased "+$scope.user.username+"'s reputation by 5"); $scope.user.reputation.overall += 5; @@ -17,8 +19,8 @@ app.service('moderationActionsFactory', function(userService) { }; $scope.subtractRep = function() { - if ($scope.subtracted && !$scope.added) return; - $scope.subtracted = true; + if ($scope.repCounter < 0) return; + $scope.repCounter -= 1; userService.subtractRep($scope.user.id).then(function() { $scope.$emit("successMessage", "Reduced "+$scope.user.username+"'s reputation by 5"); $scope.user.reputation.overall -= 5; diff --git a/mod-picker/app/assets/javascripts/Factories/notificationsFactory.js b/mod-picker/app/assets/javascripts/Factories/notificationsFactory.js index c49a98ad9..0744ac00e 100644 --- a/mod-picker/app/assets/javascripts/Factories/notificationsFactory.js +++ b/mod-picker/app/assets/javascripts/Factories/notificationsFactory.js @@ -68,14 +68,14 @@ app.service('notificationsFactory', function() { }; this.permissions = [ - "", - "You can now use a custom avatar and create new tags.", - "You can now submit, discuss, and vote on corrections.", - "You can now endorse up to 5 other users.", - "You can now submit mods to the platform.", - "You can now endorse up to 10 other users.", - "You can now endorse up to 15 other users.", - "You can now set your own user title." + /*10*/ "You can now use a custom avatar and create help pages.", + /*20*/ "You can create new tags and make curator requests.", + /*40*/ "You can now submit, discuss, and vote on corrections.", + /*80*/ "You can now endorse up to 5 other users. Reviews and Notes you submit are now automatically approved.", + /*160*/ "Mods you submit are now automatically approved. You can now upload images for mods that have none.", + /*320*/ "You can now endorse up to 10 other users. You can now update notes made by inactive users.", + /*640*/ "You can now endorse up to 15 other users.", + /*1280*/ "You can now use a custom user title." ]; var noteContentLink = diff --git a/mod-picker/app/assets/javascripts/Services/imageUtils.js b/mod-picker/app/assets/javascripts/Services/imageUtils.js index 2f85a31f9..3b33867e1 100644 --- a/mod-picker/app/assets/javascripts/Services/imageUtils.js +++ b/mod-picker/app/assets/javascripts/Services/imageUtils.js @@ -15,6 +15,9 @@ app.service('imageUtils', function() { file: new File([blob], filename), src: URL.createObjectURL(blob) }); + imageObj.sizes.sort(function(a, b) { + return (a.height || a.size) - (b.height || b.size); + }); apply(); }; }); diff --git a/mod-picker/app/assets/javascripts/Services/modLoaderService.js b/mod-picker/app/assets/javascripts/Services/modLoaderService.js index c30470a36..d20440006 100644 --- a/mod-picker/app/assets/javascripts/Services/modLoaderService.js +++ b/mod-picker/app/assets/javascripts/Services/modLoaderService.js @@ -57,7 +57,7 @@ app.service('modLoaderService', function(sitesFactory, assetUtils) { this.loadAssets = function(mod) { mod.mod_options.forEach(function(option) { - if (!option.asset_file_paths) return; + if (!option.asset_file_paths || !option.asset_file_paths.length) return; option.nestedAssets = assetUtils.getNestedAssets(option.asset_file_paths); }); }; diff --git a/mod-picker/app/assets/javascripts/Services/sortUtils.js b/mod-picker/app/assets/javascripts/Services/sortUtils.js index 2ba37016d..1c8eee491 100644 --- a/mod-picker/app/assets/javascripts/Services/sortUtils.js +++ b/mod-picker/app/assets/javascripts/Services/sortUtils.js @@ -100,8 +100,7 @@ app.service('sortUtils', function($q, categoryService, colorsFactory, modListSer groups[0].children.push(item); } // non-official ESMs go into the ESMs group - else if (handlingPlugins && plugin.filename.endsWith('.esm')) { - // TODO: Check ESM flag instead once we have it + else if (handlingPlugins && plugin.is_esm) { groups[1].children.push(item); } // for everything else we create groups based on the primary category of the mod diff --git a/mod-picker/app/assets/javascripts/Views/mod/modAnalysis.js b/mod-picker/app/assets/javascripts/Views/mod/modAnalysis.js index 976dc761d..2b3034263 100644 --- a/mod-picker/app/assets/javascripts/Views/mod/modAnalysis.js +++ b/mod-picker/app/assets/javascripts/Views/mod/modAnalysis.js @@ -28,7 +28,7 @@ app.controller('modAnalysisController', function($scope, $stateParams, $state, m var errorTypes = $scope.mod.currentPlugin.plugin_errors; errorTypes.forEach(function(errorType) { if (errorType.benign) return; - $scope.noCriticalErrors = $scope.noCriticalErrors && !errorType.length; + $scope.noCriticalErrors = $scope.noCriticalErrors && !errorType.errors.length; }); }; @@ -55,9 +55,33 @@ app.controller('modAnalysisController', function($scope, $stateParams, $state, m $scope.showBenignErrors = !$scope.showBenignErrors; }; + $scope.getStatePluginOptionId = function(optionIds) { + if ($stateParams.plugin) { + var foundPlugin = $scope.mod.plugins.find(function(plugin) { + return plugin.id == $stateParams.plugin; + }); + if (foundPlugin) optionIds.push(foundPlugin.mod_option_id); + } + }; + + $scope.getStateParamOptionIds = function(optionIds) { + if ($stateParams.options) { + $stateParams.options.split(',').forEach(function(optionId) { + if (optionIds.indexOf(optionId) == -1) optionIds.push(optionId); + }); + } + }; + + $scope.getStateOptionIds = function() { + var optionIds = []; + $scope.getStatePluginOptionId(optionIds); + $scope.getStateParamOptionIds(optionIds); + return optionIds; + }; + $scope.setCurrentSelection = function() { - // set active options - var optionIds = $stateParams.options ? $stateParams.options.split(',') : []; + // enable mod options + var optionIds = $scope.getStateOptionIds(); $scope.mod.options.forEach(function(option) { option.active = option.default || optionIds.indexOf(option.id) > -1; }); diff --git a/mod-picker/app/assets/javascripts/Views/mod/modCompatibility.js b/mod-picker/app/assets/javascripts/Views/mod/modCompatibility.js index 3254ed76d..c75603150 100644 --- a/mod-picker/app/assets/javascripts/Views/mod/modCompatibility.js +++ b/mod-picker/app/assets/javascripts/Views/mod/modCompatibility.js @@ -119,8 +119,6 @@ app.controller('modCompatibilityController', function($scope, $stateParams, $sta var statusValid = true; if (note.status === "compatibility_mod") { statusValid = !!note.compatibility_mod_id; - } else if (note.status === "compatibility_option") { - statusValid = note.compatibility_option_id || note.compatibility_plugin_id; } // compatibility note is valid if all parts valid diff --git a/mod-picker/app/assets/javascripts/Views/modList/modList.js b/mod-picker/app/assets/javascripts/Views/modList/modList.js index c60540eb6..c2e206c87 100644 --- a/mod-picker/app/assets/javascripts/Views/modList/modList.js +++ b/mod-picker/app/assets/javascripts/Views/modList/modList.js @@ -126,6 +126,9 @@ app.controller('modListController', function($scope, $rootScope, $q, $state, $st $scope.originalModList = angular.copy($scope.mod_list); $scope.removedModIds = []; + // default to editing modlist if it's the current user's active modlist + $scope.editing = $scope.activeModList; + // initialize local variables $scope.tabs = tabsFactory.buildModListTabs($scope.mod_list); $scope.pages = { @@ -457,7 +460,7 @@ app.controller('modListController', function($scope, $rootScope, $q, $state, $st }; $scope.updateCounters = function(updatedModList) { - var counts = ["tools_count", "mods_count", "plugins_count", "config_files_count"]; + var counts = ["tools_count", "mods_count", "plugins_count"]; counts.forEach(function(count) { $scope.mod_list[count] = updatedModList[count]; }); diff --git a/mod-picker/app/assets/javascripts/Views/modList/modListMods.js b/mod-picker/app/assets/javascripts/Views/modList/modListMods.js index 9ae320753..f6f79ecb8 100644 --- a/mod-picker/app/assets/javascripts/Views/modList/modListMods.js +++ b/mod-picker/app/assets/javascripts/Views/modList/modListMods.js @@ -64,17 +64,25 @@ app.controller('modListModsController', function($scope, $rootScope, $timeout, $ modListMod.mod.mod_options.forEach(function(option) { if (option.default) { option.active = true; - modListMod.mod_list_mod_options.push({ - mod_option_id: option.id + var options = modListMod.mod_list_mod_options; + var existingModOption = options.find(function(mlOption) { + return mlOption.mod_option_id == option.id; }); - $rootScope.$broadcast('modOptionAdded', option); + if (!existingModOption) { + options.push({ mod_option_id: option.id }); + $rootScope.$broadcast('modOptionAdded', option); + } } }); }; $scope.removeActiveModOptions = function(modListMod) { + modListMod.mod_list_mod_options.forEach(function(option) { + $rootScope.$broadcast('modOptionRemoved', option.mod_option_id); + }); + modListMod.mod_list_mod_options = []; modListMod.mod && modListMod.mod.mod_options.forEach(function(option) { - if (option.active) $rootScope.$broadcast('modOptionRemoved', option.id); + option.active = false; }); }; diff --git a/mod-picker/app/assets/javascripts/Views/modList/modListPlugins.js b/mod-picker/app/assets/javascripts/Views/modList/modListPlugins.js index 9dd1cc973..b9395d89a 100644 --- a/mod-picker/app/assets/javascripts/Views/modList/modListPlugins.js +++ b/mod-picker/app/assets/javascripts/Views/modList/modListPlugins.js @@ -84,6 +84,15 @@ app.controller('modListPluginsController', function($scope, $q, $timeout, catego customPlugin.compatibility_note_id = compatibilityNoteId; }; + $scope.forModOptionPlugins = function(modOptionId, callback) { + listUtils.forEachItem($scope.model.plugins, function(modListPlugin) { + if (!modListPlugin.plugin) return; + if (modListPlugin.plugin.mod_option_id == modOptionId) { + callback(modListPlugin); + } + }); + }; + // CUSTOM CALLBACKS $scope.addCustomPluginCallback = function(options) { if (options.noteId) { @@ -132,14 +141,12 @@ app.controller('modListPluginsController', function($scope, $q, $timeout, catego data.mod_list_plugins.forEach($scope.addNewPluginItem); }); $scope.$on('modOptionRemoved', function(event, modOptionId) { - var model = $scope.model.plugins; - listUtils.forMatchingItems(model, 'mod_option_id', modOptionId, $scope.removePlugin); + $scope.forModOptionPlugins(modOptionId, $scope.removePlugin); listUtils.forMatching($scope.plugins_store, 'mod_option_id', modOptionId, listUtils.destroyItem); }); $scope.$on('modOptionAdded', function(event, modOption) { var modOptionId = modOption.id; - var model = $scope.model.plugins; - listUtils.forMatchingItems(model, 'mod_option_id', modOptionId, $scope.recoverPlugin); + $scope.forModOptionPlugins(modOptionId, $scope.recoverPlugin); listUtils.forMatching($scope.plugins_store, 'mod_option_id', modOptionId, listUtils.recoverItem); $scope.addModOptionPluginsToStore(modOption); }); diff --git a/mod-picker/app/assets/javascripts/helpcenter.js b/mod-picker/app/assets/javascripts/helpcenter.js index dfb085b1c..0f13db266 100644 --- a/mod-picker/app/assets/javascripts/helpcenter.js +++ b/mod-picker/app/assets/javascripts/helpcenter.js @@ -1,3 +1,10 @@ +//= require angular.min.1.5.1.js +//= require marked.min.js +//= require angular-marked.min.js +//= require angular-relative-date.min.js +//= require angular-animate.min.js +//= require simplemde.min.js +//= require spin.min.js //= require_self //= require ./polyfills.js //= require BackendAPI/backend.js @@ -15,6 +22,10 @@ //= require Services/pageUtils.js //= require Services/ObjectUtils.js //= require_tree ./Directives/help +/* + Mod Picker Help Center v1.0 + (c) 2016 Mod Picker, LLC. https://www.modpicker.com +*/ var app = angular.module('helpCenter', [ 'ngAnimate', 'hc.marked', 'relativeDate' diff --git a/mod-picker/app/assets/javascripts/landing.js b/mod-picker/app/assets/javascripts/landing.js index 80c7e89ce..bb2da2ee9 100644 --- a/mod-picker/app/assets/javascripts/landing.js +++ b/mod-picker/app/assets/javascripts/landing.js @@ -1,7 +1,13 @@ +//= require angular.min.1.5.1.js +//= require angular-animate.min.js //= require_self //= require ./polyfills.js //= require Directives/shared/sticky.js //= require Services/ObjectUtils.js +/* + Mod Picker Landing Page v1.0 + (c) 2016 Mod Picker, LLC. https://www.modpicker.com +*/ var app = angular.module('landing', [ 'ngAnimate' diff --git a/mod-picker/app/assets/javascripts/modpicker-vendor.js b/mod-picker/app/assets/javascripts/modpicker-vendor.js new file mode 100644 index 000000000..3b7d69245 --- /dev/null +++ b/mod-picker/app/assets/javascripts/modpicker-vendor.js @@ -0,0 +1,14 @@ +//= require angular.min.1.5.1.js +//= require marked.min.js +//= require bindonce.min.js +//= require angular-marked.min.js +//= require angular-drag-and-drop-lists.min.js +//= require angular-ui-router.min.js +//= require ct-ui-router-extras.min.js +//= require angular-smooth-scroll.min.js +//= require angular-relative-date.min.js +//= require rzslider.min.js +//= require angular-animate.min.js +//= require angular-elastic-input.min.js +//= require simplemde.min.js +//= require spin.min.js \ No newline at end of file diff --git a/mod-picker/app/assets/javascripts/modpicker.js b/mod-picker/app/assets/javascripts/modpicker.js index 0a22a6345..c7a7c6000 100644 --- a/mod-picker/app/assets/javascripts/modpicker.js +++ b/mod-picker/app/assets/javascripts/modpicker.js @@ -7,6 +7,10 @@ //= require_tree ./Services //= require_tree ./Views //= stub_tree Directives/help +/* + Mod Picker v1.0 + (c) 2016 Mod Picker, LLC. https://www.modpicker.com +*/ var app = angular.module('modPicker', [ 'ui.router', 'rzModule', 'ngAnimate', 'puElasticInput', 'hc.marked', 'smoothScroll', 'relativeDate', 'ct.ui.router.extras', 'dndLists', 'pasvaz.bindonce' diff --git a/mod-picker/app/assets/stylesheets/components/gridItems.scss b/mod-picker/app/assets/stylesheets/components/gridItems.scss index 3c8a867ee..448b5da3b 100644 --- a/mod-picker/app/assets/stylesheets/components/gridItems.scss +++ b/mod-picker/app/assets/stylesheets/components/gridItems.scss @@ -191,6 +191,10 @@ grid-items { } } +grid-item, table-item { + @include user-select(none); +} + table-items { display: block; overflow-x: auto; diff --git a/mod-picker/app/assets/stylesheets/components/pluginMetadata.scss b/mod-picker/app/assets/stylesheets/components/pluginMetadata.scss index 6ca8ff2ca..a665274c1 100644 --- a/mod-picker/app/assets/stylesheets/components/pluginMetadata.scss +++ b/mod-picker/app/assets/stylesheets/components/pluginMetadata.scss @@ -1,4 +1,3 @@ -/* css for plugin-metadata */ plugin-metadata { .stat-data { width: calc(100% - 170px); @@ -9,4 +8,18 @@ plugin-metadata { white-space: pre-line; word-wrap: break-word; } + + .flag { + margin-left: 4px; + font-weight: normal; + font-size: 12px; + padding: 0 0.5rem; + text-transform: uppercase; + cursor: default; + } + + .esm-flag { + color: $success_secondary; + border: 1px solid $success_secondary; + } } \ No newline at end of file diff --git a/mod-picker/app/assets/stylesheets/general/tabs.scss b/mod-picker/app/assets/stylesheets/general/tabs.scss index a47dcf8d7..33de449d2 100644 --- a/mod-picker/app/assets/stylesheets/general/tabs.scss +++ b/mod-picker/app/assets/stylesheets/general/tabs.scss @@ -5,11 +5,11 @@ display: inline-block; cursor: pointer; color: $action_text_color; - padding: 9px 16px 9px 16px;//half of font size high + padding: 9px 16px; border: 1px solid $border_color; border-bottom: 0; background-color: $action_color; - margin-right: 2px; + margin-right: 3px; &:hover { background-color: $bar_highlight_color; @@ -23,6 +23,14 @@ } } +two-columns { + .smaller-tabs { + a { + padding: 9px 11px; + } + } +} + .secondary-tabs { a.selected-tab { background-color: $secondary_background; diff --git a/mod-picker/app/assets/stylesheets/help.scss b/mod-picker/app/assets/stylesheets/help.scss index 676061ae8..e998280fb 100644 --- a/mod-picker/app/assets/stylesheets/help.scss +++ b/mod-picker/app/assets/stylesheets/help.scss @@ -1,4 +1,5 @@ @import +'simplemde.min', 'general/mixins', 'general/buttons', 'general/forms', diff --git a/mod-picker/app/assets/stylesheets/help/content.scss b/mod-picker/app/assets/stylesheets/help/content.scss index 0d94c8951..ac6ffb720 100644 --- a/mod-picker/app/assets/stylesheets/help/content.scss +++ b/mod-picker/app/assets/stylesheets/help/content.scss @@ -64,6 +64,6 @@ body { } .help-page-body p { - margin-left: 5px; + margin-left: 3px; } } diff --git a/mod-picker/app/assets/stylesheets/landing/content.scss b/mod-picker/app/assets/stylesheets/landing/content.scss index 4ca070784..2f53cc3a1 100644 --- a/mod-picker/app/assets/stylesheets/landing/content.scss +++ b/mod-picker/app/assets/stylesheets/landing/content.scss @@ -17,19 +17,21 @@ h1 { } h2 { + font-size: 1.5em; font-weight: normal; max-width: 900px; margin: 20px auto; } section { - padding: 60px; + padding-top: 60px; + padding-bottom: 120px; text-align: center; img { max-height: 50vh; margin-top: 20px; - box-shadow: 2px 2px 5px 2px $text_color; + box-shadow: 3px 3px 16px 1px $text_color; max-width: 95%; } } @@ -147,7 +149,7 @@ section.base { .low, .base { img { - box-shadow: 2px 2px 5px 2px darken($text_color, 14%); + box-shadow: 3px 3px 16px 1px darken($text_color, 14%); } } diff --git a/mod-picker/app/assets/stylesheets/main.scss b/mod-picker/app/assets/stylesheets/main.scss index 5dade14f7..04fc0615a 100644 --- a/mod-picker/app/assets/stylesheets/main.scss +++ b/mod-picker/app/assets/stylesheets/main.scss @@ -1,4 +1,6 @@ @import +'rzslider.min', +'simplemde.min', 'general/mixins', 'general/urls', 'general/buttons', diff --git a/mod-picker/app/assets/stylesheets/main/header.scss b/mod-picker/app/assets/stylesheets/main/header.scss index fa588c7b9..15fdee320 100644 --- a/mod-picker/app/assets/stylesheets/main/header.scss +++ b/mod-picker/app/assets/stylesheets/main/header.scss @@ -151,8 +151,8 @@ nav { } #contributions-dropdown { - left: 157px; - width: 180px; + left: 155px; + width: 182px; a { display: block; diff --git a/mod-picker/app/controllers/mods_controller.rb b/mod-picker/app/controllers/mods_controller.rb index d69273f91..47fabf622 100644 --- a/mod-picker/app/controllers/mods_controller.rb +++ b/mod-picker/app/controllers/mods_controller.rb @@ -400,9 +400,9 @@ def mod_params custom_sources_attributes: [:label, :url], required_mods_attributes: [:required_id], tag_names: [], - mod_options_attributes: [:name, :display_name, :size, :default, :is_fomod_option, + mod_options_attributes: [:name, :display_name, :size, :md5_hash, :default, :is_installer_option, asset_paths: [], - plugin_dumps: [:filename, :author, :description, :crc_hash, :record_count, :override_count, :file_size, + plugin_dumps: [:filename, :is_esm, :author, :description, :crc_hash, :record_count, :override_count, :file_size, master_plugins: [:filename, :crc_hash], plugin_record_groups_attributes: [:sig, :record_count, :override_count], plugin_errors_attributes: [:signature, :form_id, :group, :path, :name, :data], @@ -418,9 +418,9 @@ def mod_update_params custom_sources_attributes: [:id, :label, :url, :_destroy], config_files_attributes: [:id, :filename, :install_path, :text_body, :_destroy], tag_names: [], - mod_options_attributes: [:id, :name, :display_name, :size, :default, :is_fomod_option, :_destroy, + mod_options_attributes: [:id, :name, :display_name, :size, :md5_hash, :default, :is_installer_option, :_destroy, asset_paths: [], - plugin_dumps: [:id, :filename, :author, :description, :crc_hash, :record_count, :override_count, :file_size, :_destroy, + plugin_dumps: [:id, :filename, :is_esm, :author, :description, :crc_hash, :record_count, :override_count, :file_size, :_destroy, master_plugins: [:filename, :crc_hash], plugin_record_groups_attributes: [:sig, :record_count, :override_count], plugin_errors_attributes: [:signature, :form_id, :group, :path, :name, :data], diff --git a/mod-picker/app/models/ability.rb b/mod-picker/app/models/ability.rb index 5f6930176..a1a174609 100644 --- a/mod-picker/app/models/ability.rb +++ b/mod-picker/app/models/ability.rb @@ -145,13 +145,13 @@ def initialize(user) cannot [:update, :hide], Mod, { disallow_contributors: true, mod_authors: { user_id: user.id, role: 1 } } # abilities tied to reputation - if user.reputation.overall >= 5 - # TODO: Remove this after beta - can :create, Tag # can create new tags + if user.reputation.overall >= 10 + # can create new help pages + can :create, HelpPage end if user.reputation.overall >= 20 - # TODO: Uncomment this after beta - #can :create, Tag # can create new tags + # can create new tags and curator requests + can :create, Tag can :create, CuratorRequest end if user.reputation.overall >= 40 @@ -161,11 +161,16 @@ def initialize(user) cannot :create, Correction, { correctable: { submitted_by: user.id } } can :create, Correction, { correctable_type: "Mod" } - # can agree/disagree with corrections, give reputation other users, and - # can create new help pages + # can agree/disagree with corrections can :create, AgreementMark - can :create, ReputationLink # can - can :create, HelpPage + end + if user.reputation.overall >= 80 + # can give reputation other users + can :create, ReputationLink + end + if user.reputation.overall >= 160 + # can add images to mods that have none + can :add_image, Mod end if user.reputation.overall >= 320 # can update compatibility notes, install order notes, and @@ -198,7 +203,7 @@ def initialize(user) can :update, UserBio, { user_id: user.id } # abilities tied to reputation - if user.reputation.overall >= 20 + if user.reputation.overall >= 10 can :set_avatar, User, id: user.id # custom avatar end if user.reputation.overall >= 1280 @@ -210,6 +215,7 @@ def initialize(user) settings = user.settings unless settings.present? && settings.allow_adult_content cannot :read, Mod, { has_adult_content: true } + cannot :read, Plugin, { has_adult_content: true } cannot :read, ModList, { has_adult_content: true } cannot :read, Review, { has_adult_content: true } cannot :read, CompatibilityNote, { has_adult_content: true } diff --git a/mod-picker/app/models/concerns/correctable.rb b/mod-picker/app/models/concerns/correctable.rb index ff939439b..27c94046d 100644 --- a/mod-picker/app/models/concerns/correctable.rb +++ b/mod-picker/app/models/concerns/correctable.rb @@ -21,4 +21,11 @@ def compute_standing self.standing = :good end end + + def correction_passed(correction) + update_columns({ + standing: self.class.standing[:bad], + corrector_id: correction.submitted_by + }) + end end \ No newline at end of file diff --git a/mod-picker/app/models/correction.rb b/mod-picker/app/models/correction.rb index 7cadc7648..f95e7aebc 100644 --- a/mod-picker/app/models/correction.rb +++ b/mod-picker/app/models/correction.rb @@ -61,30 +61,35 @@ class Correction < ActiveRecord::Base after_save :recompute_correctable_standing after_destroy :recompute_correctable_standing + # CONSTANTS + MINIMUM_VOTES = 4 + + # METHODS def self.close(id) correction = Correction.find(id) if correction.status == :open - if correction.agree_count > @correction.disagree_count - correction.status = :passed - # if we're dealing with a mod, update the mod's status - if correction.correctable_type == 'Mod' - mod = correction.correctable - mod.update_columns(status: Mod.statuses[correction.mod_status]) - else - # if we're dealing with a contribution, update its standing and open for editing - contribution = correction.correctable - contribution.update_columns({ - standing: contribution.class.standing[:bad], - corrector_id: correction.submitted_by - }) - end - else - correction.status = :failed - end + correction.passed? ? correction.pass : correction.fail correction.save end end + def pass + self.status = :passed + correctable.correction_passed(self) + end + + def fail + self.status = :failed + end + + def has_minimum_votes? + agree_count + disagree_count >= MINIMUM_VOTES + end + + def passed? + has_minimum_votes? && agree_count > disagree_count + end + def mod_author_users if correctable_type == "Mod" correctable.author_users diff --git a/mod-picker/app/models/lover_info.rb b/mod-picker/app/models/lover_info.rb index d9da323e3..43cd78f61 100644 --- a/mod-picker/app/models/lover_info.rb +++ b/mod-picker/app/models/lover_info.rb @@ -31,9 +31,7 @@ def url def link_uploader bio = UserBio.find_by(lover_username: uploaded_by) - if bio.present? && mod_id.present? - ModAuthor.find_or_create_by(mod_id: mod_id, user_id: bio.user_id) - end + ModAuthor.add_author(mod_id, bio.user_id) if bio.present? && mod_id.present? end def can_scrape_statistics? diff --git a/mod-picker/app/models/mod.rb b/mod-picker/app/models/mod.rb index 206350654..2bd4b0758 100644 --- a/mod-picker/app/models/mod.rb +++ b/mod-picker/app/models/mod.rb @@ -174,6 +174,10 @@ class Mod < ActiveRecord::Base # CALLBACKS before_save :touch_updated + def correction_passed(correction) + update_columns(status: Mod.statuses[correction.mod_status]) + end + def asset_file_paths mod_asset_files.eager_load(:asset_file).pluck(:subpath, :path).map { |item| item.join('') } end diff --git a/mod-picker/app/models/mod_author.rb b/mod-picker/app/models/mod_author.rb index 4f47cd730..ec2368f29 100644 --- a/mod-picker/app/models/mod_author.rb +++ b/mod-picker/app/models/mod_author.rb @@ -26,11 +26,16 @@ class ModAuthor < ActiveRecord::Base after_save :update_user_role, :hide_reviews before_destroy :update_user_role, :unhide_reviews + def self.add_author(mod_id, user_id) + existing_author = ModAuthor.find_by(mod_id: mod_id, user_id: user_id) + existing_author.update(role: 0) if existing_author.present? + ModAuthor.create(mod_id: mod_id, user_id: user_id, role: 0) + end + def self.link_author(model, user_id, username) infos = model.where(uploaded_by: username) - infos.each do |info| - ModAuthor.find_or_create_by(mod_id: info.mod_id, user_id: user_id) if info.mod_id.present? + add_author(info.mod_id, user_id) if info.mod_id.present? end end diff --git a/mod-picker/app/models/mod_list.rb b/mod-picker/app/models/mod_list.rb index 9b6c2b561..3f0717008 100644 --- a/mod-picker/app/models/mod_list.rb +++ b/mod-picker/app/models/mod_list.rb @@ -101,10 +101,11 @@ class ModList < ActiveRecord::Base counter_cache_on :submitter bool_counter_cache :mod_list_mods, :is_utility, { true => :tools, false => :mods } bool_counter_cache :custom_mods, :is_utility, { true => :custom_tools, false => :custom_mods } - counter_cache :custom_plugins, :config_files, :custom_config_files, :ignored_notes, :stars + counter_cache :mod_list_config_files, column: 'config_files_count' + counter_cache :mod_list_plugins, column: 'plugins_count' + counter_cache :custom_plugins, :custom_config_files, :ignored_notes, :stars counter_cache :mod_list_tags, column: 'tags_count' counter_cache :comments, conditional: { commentable_type: 'ModList' } - counter_cache :plugins, custom_reflection: { klass: Plugin, query_method: 'mod_list_count_subquery' } # VALIDATIONS validates :game_id, :submitted_by, :name, presence: true @@ -257,7 +258,7 @@ def incompatible_mod_ids return [] if mod_ids.empty? # get incompatible mod ids - incompatible_ids = CompatibilityNote.status([0, 1]).mod(mod_ids).pluck(:first_mod_id, :second_mod_id) + incompatible_ids = CompatibilityNote.visible.status([0, 1]).mod(mod_ids).pluck(:first_mod_id, :second_mod_id) # return array of unique mod ids from the notes, excluding mod list mod ids incompatible_ids.flatten(1).uniq - mod_ids end diff --git a/mod-picker/app/models/mod_option.rb b/mod-picker/app/models/mod_option.rb index a6f92eab0..0b7a68537 100644 --- a/mod-picker/app/models/mod_option.rb +++ b/mod-picker/app/models/mod_option.rb @@ -39,7 +39,7 @@ def plugin_dumps=(value) # INSTANCE METHODS def get_base_paths - if !is_fomod_option + if !is_installer_option basepaths = DataPathUtils.get_base_paths(@asset_paths) else basepaths = [""] @@ -49,7 +49,7 @@ def get_base_paths def create_asset_file(basepaths, path) basepath = basepaths.find { |basepath| path.start_with?(basepath) } if basepath.nil? - mod_asset_files.create(subpath: path) + mod_asset_files.create(subpath: path) unless path.blank? else asset_file = AssetFile.find_or_create_by(game_id: mod.game_id, path: path.sub(basepath, '')) mod_asset_files.create(asset_file_id: asset_file.id, subpath: basepath) diff --git a/mod-picker/app/models/nexus_info.rb b/mod-picker/app/models/nexus_info.rb index 0628b10e3..93f063348 100644 --- a/mod-picker/app/models/nexus_info.rb +++ b/mod-picker/app/models/nexus_info.rb @@ -42,9 +42,7 @@ def after_scrape def link_uploader bio = UserBio.find_by(nexus_username: uploaded_by) - if bio.present? && mod_id.present? - ModAuthor.find_or_create_by(mod_id: mod_id, user_id: bio.user_id) - end + ModAuthor.add_author(mod_id, bio.user_id) if bio.present? && mod_id.present? end def compute_extra_metrics diff --git a/mod-picker/app/models/plugin.rb b/mod-picker/app/models/plugin.rb index 844c1dd3b..80f9dc21d 100644 --- a/mod-picker/app/models/plugin.rb +++ b/mod-picker/app/models/plugin.rb @@ -136,14 +136,6 @@ def prepare_to_destroy ModListPlugin.where(plugin_id: id).delete_all end - def self.mod_list_count_subquery - mod_list_plugins_table = ModListPlugin.arel_table - arel_table.join(mod_list_plugins_table). - on(arel_table[:id].eq(mod_list_plugins_table[:plugin_id])). - where(ModList.arel_table[:id].eq(mod_list_plugins_table[:mod_list_id])). - project(Arel.sql('*').count) - end - def formatted_overrides output = {} self.overrides.each do |ovr| diff --git a/mod-picker/app/models/user.rb b/mod-picker/app/models/user.rb index bdacc3d5f..3d45755cb 100644 --- a/mod-picker/app/models/user.rb +++ b/mod-picker/app/models/user.rb @@ -145,11 +145,11 @@ def comments_disabled? end def has_auto_approval? - reputation.overall > 20 + reputation.overall > 40 end def has_mod_auto_approval? - reputation.overall > 80 + reputation.overall > 160 end def subscribed_to?(event) diff --git a/mod-picker/app/models/user_bio.rb b/mod-picker/app/models/user_bio.rb index ea51c1221..2d99215ac 100644 --- a/mod-picker/app/models/user_bio.rb +++ b/mod-picker/app/models/user_bio.rb @@ -11,6 +11,13 @@ class UserBio < ActiveRecord::Base # CALLBACKS after_create :generate_verification_tokens + # CONSTANTS + SITE_CODES = { + "Nexus Mods" => "nexus", + "Lover's Lab" => "lover", + "Steam Workshop" => "workshop" + } + def get_token "ModPicker:#{SecureRandom.hex(4).to_s.upcase}" end @@ -22,125 +29,90 @@ def generate_verification_tokens self.save end - def verify_account(site, user_path) + def verify_account(site_label, user_path) begin - case site - when "Nexus Mods" - verify_nexus_account(user_path) - when "Lover's Lab" - verify_lover_account(user_path) - when "Steam Workshop" - verify_workshop_account(user_path) - else - false - end + method_name = "verify_#{SITE_CODES[site_label]}_account" + public_send(method_name, user_path) if respond_to?(method_name) rescue RestClient::NotFound => e - raise " we couldn't find a #{site} user at that URL" + raise " we couldn't find a #{site_label} user at that URL" end end + def reset_account(site) + public_send("#{site}_verification_token=", get_token) + public_send("#{site}_user_path=", nil) + public_send("#{site}_username=", nil) + public_send("#{site}_date_joined=", nil) if respond_to?("#{site}_date_joined=") + public_send("#{site}_posts_count=", 0) if respond_to?("#{site}_posts_count=") + public_send("#{site}_submissions_count=", 0) if respond_to?("#{site}_submissions_count=") + public_send("#{site}_followers_count=", 0) if respond_to?("#{site}_followers_count=") + save + end + + def write_user_data(site, user_path, user_data, stat_data=nil) + public_send("#{site}_user_path=", user_path) + public_send("#{site}_username=", user_data[:username]) + public_send("#{site}_date_joined=", user_data[:date_joined]) if user_data.has_key?(:date_joined) + public_send("#{site}_posts_count=", user_data[:posts_count]) if user_data.has_key?(:posts_count) + public_send("#{site}_submissions_count=", stat_data[:submissions_count]) if stat_data.present? + public_send("#{site}_followers_count=", stat_data[:followers_count]) if stat_data.present? + end + def verify_nexus_account(user_path) # exit if we don't have a nexus_user_path - if user_path.nil? - return false - end + return false if user_path.nil? # scrape using the Nexus Helper user_data = NexusHelper.scrape_user(user_path) - # verify the token + # verify the token, write data, populate mod author records, and save if user_data[:last_status] == nexus_verification_token - # write fields to bio - self.nexus_user_path = user_path - self.nexus_username = user_data[:username] - self.nexus_date_joined = user_data[:date_joined] - self.nexus_posts_count = user_data[:posts_count] - - # populate mod author records + write_user_data(:nexus, user_path, user_data) ModAuthor.link_author(NexusInfo, user_id, nexus_username) - - # save bio - save! + save end end def reset_nexus_account - self.nexus_verification_token = get_token - self.nexus_user_path = nil - self.nexus_username = nil - self.nexus_date_joined = nil - self.nexus_posts_count = 0 - save + reset_account(:nexus) end def verify_lover_account(user_path) # exit if we don't have an account_path - if user_path.nil? - return false - end + return false if user_path.nil? # scrape using the Lover Helper user_data = LoverHelper.scrape_user(user_path) - # verify the token + # verify the token, write data, populate mod author records, and save if user_data[:last_status] == lover_verification_token - # write fields to bio - self.lover_user_path = user_path - self.lover_username = user_data[:username] - self.lover_date_joined = user_data[:date_joined] - self.lover_posts_count = user_data[:posts_count] - - # populate mod author records + write_user_data(:lover, user_path, user_data) ModAuthor.link_author(LoverInfo, user_id, lover_username) - - # save bio - save! + save end end def reset_lover_account - self.lover_verification_token = get_token - self.lover_user_path = nil - self.lover_username = nil - self.lover_date_joined = nil - self.lover_posts_count = 0 - save + reset_account(:lover) end def verify_workshop_account(user_path) # exit if we don't have a steam_username - if user_path.nil? - return - end + return false if user_path.nil? # scrape using the workshop helper user_data = WorkshopHelper.scrape_user(user_path) - # verify the token + # verify the token, scrape workshop stats, write data, populate mod author records, and save if user_data[:matched_comment] == workshop_verification_token - # scrape user's workshop stats workshop_stats = WorkshopHelper.scrape_workshop_stats(user_path) - - # write fields to bio - self.workshop_user_path = user_path - self.workshop_username = user_data[:username] - self.workshop_submissions_count = workshop_stats[:submissions_count] - self.workshop_followers_count = workshop_stats[:followers_count] - - # populate mod author records + write_user_data(:workshop, user_path, user_data, workshop_stats) ModAuthor.link_author(WorkshopInfo, user_id, workshop_username) - - # save bio - save! + save end end def reset_workshop_account - self.workshop_verification_token = get_token - self.workshop_user_path = nil - self.workshop_username = nil - self.workshop_submissions_count = 0 - self.workshop_followers_count = 0 - save + reset_account(:workshop) end end diff --git a/mod-picker/app/models/workshop_info.rb b/mod-picker/app/models/workshop_info.rb index 40ed82284..72ed599ca 100644 --- a/mod-picker/app/models/workshop_info.rb +++ b/mod-picker/app/models/workshop_info.rb @@ -31,9 +31,7 @@ def url def link_uploader bio = UserBio.find_by(workshop_username: uploaded_by) - if bio.present? && mod_id.present? - ModAuthor.find_or_create_by(mod_id: mod_id, user_id: bio.user_id) - end + ModAuthor.add_author(mod_id, bio.user_id) if bio.present? && mod_id.present? end def self.can_scrape_statistics? diff --git a/mod-picker/app/views/layouts/application.html.erb b/mod-picker/app/views/layouts/application.html.erb index 360cf1682..79f90c918 100644 --- a/mod-picker/app/views/layouts/application.html.erb +++ b/mod-picker/app/views/layouts/application.html.erb @@ -5,9 +5,8 @@ - <%= stylesheet_link_tag 'rzslider.min' %> - <%= stylesheet_link_tag 'simplemde.min' %> - <%= javascript_include_tag 'angular.min.1.5.1' %> + <%= javascript_include_tag 'modpicker-vendor' %> + " ng-href="{{currentTheme}}" /> - '" /> <%= yield %> - - <%= javascript_include_tag 'marked.min' %> - <%= javascript_include_tag 'bindonce' %> - <%= javascript_include_tag 'angular-marked.min' %> - <%= javascript_include_tag 'angular-drag-and-drop-lists.min' %> - <%= javascript_include_tag 'angular-ui-router.min' %> - <%= javascript_include_tag 'ct-ui-router-extras.min' %> - <%= javascript_include_tag 'angular-smooth-scroll.min' %> - <%= javascript_include_tag 'heartcode-canvasloader-min' %> - <%= javascript_include_tag 'angular-relative-date.min' %> - <%= javascript_include_tag 'rzslider.min' %> - <%= javascript_include_tag 'angular-animate.min' %> - <%= javascript_include_tag 'angular-elastic-input.min' %> - <%= javascript_include_tag 'simplemde.min' %> - <%= javascript_include_tag 'spin.min' %> <%= javascript_include_tag 'modpicker' %> diff --git a/mod-picker/app/views/layouts/help.html.erb b/mod-picker/app/views/layouts/help.html.erb index b91f317cc..90bbaaa7b 100644 --- a/mod-picker/app/views/layouts/help.html.erb +++ b/mod-picker/app/views/layouts/help.html.erb @@ -3,17 +3,17 @@ <%= yield :head %> + - <%= stylesheet_link_tag 'simplemde.min' %> - <%= javascript_include_tag 'angular.min.1.5.1' %> - + <%= stylesheet_link_tag 'help/High Hrothgar' %> + <%= javascript_include_tag 'helpcenter' %> + + - <%= stylesheet_link_tag 'help/High Hrothgar' %>
@@ -69,13 +69,5 @@ - -<%= javascript_include_tag 'marked.min' %> -<%= javascript_include_tag 'angular-marked.min' %> -<%= javascript_include_tag 'angular-relative-date.min' %> -<%= javascript_include_tag 'angular-animate.min' %> -<%= javascript_include_tag 'simplemde.min' %> -<%= javascript_include_tag 'spin.min' %> -<%= javascript_include_tag 'helpcenter' %> \ No newline at end of file diff --git a/mod-picker/app/views/layouts/landing.html.erb b/mod-picker/app/views/layouts/landing.html.erb index fb9740449..6ace8a9eb 100644 --- a/mod-picker/app/views/layouts/landing.html.erb +++ b/mod-picker/app/views/layouts/landing.html.erb @@ -3,21 +3,26 @@ Mod Picker + + + + + + + + + + + + + - <%= javascript_include_tag 'angular.min.1.5.1' %> + <%= javascript_include_tag 'landing' %> <%= stylesheet_link_tag 'landing/High Hrothgar' %> <%= yield %> - -<%= javascript_include_tag 'angular-ui-router.min' %> -<%= javascript_include_tag 'ct-ui-router-extras.min' %> -<%= javascript_include_tag 'angular-smooth-scroll.min' %> -<%= javascript_include_tag 'heartcode-canvasloader-min' %> -<%= javascript_include_tag 'angular-animate.min' %> -<%= javascript_include_tag 'landing' %> - \ No newline at end of file diff --git a/mod-picker/db/migrate/20161114011433_fix_category_priority_typos.rb b/mod-picker/db/migrate/20161114011433_fix_category_priority_typos.rb new file mode 100644 index 000000000..e9f1bed11 --- /dev/null +++ b/mod-picker/db/migrate/20161114011433_fix_category_priority_typos.rb @@ -0,0 +1,17 @@ +class FixCategoryPriorityTypos < ActiveRecord::Migration + def change + catQuests = Category.where(name: "Gameplay - Quests").first + catNewChars = Category.where(name: "New Characters").first + catImmersionAndRolePlaying = Category.where(name: "Gameplay - Immersion & Role-playing").first + + CategoryPriority.find_by( + dominant_id: catQuests.id, + recessive_id: catNewChars.id + ).update(description: 'New or altered quests often involve new characters.') + + CategoryPriority.find_by( + dominant_id: catQuests.id, + recessive_id: catImmersionAndRolePlaying.id + ).update(description: 'New or altered quests often increase gameplay immersion and offer new role-playing experiences.') + end +end diff --git a/mod-picker/db/migrate/20161114054608_add_md5_hash_to_mod_options.rb b/mod-picker/db/migrate/20161114054608_add_md5_hash_to_mod_options.rb new file mode 100644 index 000000000..2e11a7263 --- /dev/null +++ b/mod-picker/db/migrate/20161114054608_add_md5_hash_to_mod_options.rb @@ -0,0 +1,5 @@ +class AddMd5HashToModOptions < ActiveRecord::Migration + def change + add_column :mod_options, :md5_hash, :string, limit: 32, after: :size + end +end diff --git a/mod-picker/db/migrate/20161115064748_add_is_esm_to_plugins.rb b/mod-picker/db/migrate/20161115064748_add_is_esm_to_plugins.rb new file mode 100644 index 000000000..195009608 --- /dev/null +++ b/mod-picker/db/migrate/20161115064748_add_is_esm_to_plugins.rb @@ -0,0 +1,6 @@ +class AddIsEsmToPlugins < ActiveRecord::Migration + def change + add_column :plugins, :is_esm, :boolean, default: false, null: true + Plugin.where("filename LIKE '%.esm'").update_all(is_esm: true) + end +end diff --git a/mod-picker/db/migrate/20161116000543_rename_is_mod_option_to_is_installer_option.rb b/mod-picker/db/migrate/20161116000543_rename_is_mod_option_to_is_installer_option.rb new file mode 100644 index 000000000..86451d189 --- /dev/null +++ b/mod-picker/db/migrate/20161116000543_rename_is_mod_option_to_is_installer_option.rb @@ -0,0 +1,5 @@ +class RenameIsModOptionToIsInstallerOption < ActiveRecord::Migration + def change + rename_column :mod_options, :is_fomod_option, :is_installer_option + end +end diff --git a/mod-picker/db/schema.rb b/mod-picker/db/schema.rb index a1b535707..4098eb09e 100644 --- a/mod-picker/db/schema.rb +++ b/mod-picker/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161107235237) do +ActiveRecord::Schema.define(version: 20161116000543) do create_table "agreement_marks", id: false, force: :cascade do |t| t.integer "correction_id", limit: 4, null: false @@ -574,14 +574,15 @@ add_index "mod_lists", ["submitted_by"], name: "created_by", using: :btree create_table "mod_options", force: :cascade do |t| - t.integer "mod_id", limit: 4, null: false - t.string "name", limit: 128, null: false - t.string "display_name", limit: 128, null: false - t.integer "size", limit: 8, default: 0, null: false - t.boolean "default", default: false, null: false - t.boolean "is_fomod_option", default: false, null: false - t.integer "asset_files_count", limit: 4, default: 0, null: false - t.integer "plugins_count", limit: 4, default: 0, null: false + t.integer "mod_id", limit: 4, null: false + t.string "name", limit: 128, null: false + t.string "display_name", limit: 128, null: false + t.integer "size", limit: 8, default: 0, null: false + t.string "md5_hash", limit: 32 + t.boolean "default", default: false, null: false + t.boolean "is_installer_option", default: false, null: false + t.integer "asset_files_count", limit: 4, default: 0, null: false + t.integer "plugins_count", limit: 4, default: 0, null: false end add_index "mod_options", ["mod_id"], name: "fk_rails_e37829130d", using: :btree @@ -741,6 +742,7 @@ t.integer "mod_lists_count", limit: 4, default: 0, null: false t.integer "load_order_notes_count", limit: 4, default: 0, null: false t.boolean "has_adult_content", default: false, null: false + t.boolean "is_esm", default: false end add_index "plugins", ["game_id"], name: "fk_rails_5a7ba47709", using: :btree diff --git a/mod-picker/db/static_seeds.rb b/mod-picker/db/static_seeds.rb index 5d8bb853e..e88722444 100644 --- a/mod-picker/db/static_seeds.rb +++ b/mod-picker/db/static_seeds.rb @@ -546,12 +546,12 @@ def seed_categories CategoryPriority.create( dominant_id: catQuests.id, recessive_id: catNewChars.id, - description: 'New or alterred quests often involve new characters.' + description: 'New or altered quests often involve new characters.' ) CategoryPriority.create( dominant_id: catQuests.id, recessive_id: catImmersionAndRolePlaying.id, - description: 'New or alterred quests often increase gameplay immersion and offer new role-playing experiences.' + description: 'New or altered quests often increase gameplay immersion and offer new role-playing experiences.' ) CategoryPriority.create( dominant_id: catNewLands.id, diff --git a/mod-picker/lib/tasks/reset.rake b/mod-picker/lib/tasks/reset.rake index f5e2b93f6..b6000fe1a 100644 --- a/mod-picker/lib/tasks/reset.rake +++ b/mod-picker/lib/tasks/reset.rake @@ -113,6 +113,14 @@ namespace :reset do end end + task empty_mod_asset_files: :environment do + puts "\nDestroying empty mod asset files" + empty_mod_asset_files = ModAssetFile.where(subpath: "", asset_file_id: nil) + count = empty_mod_asset_files.length + empty_mod_asset_files.destroy_all + puts "#{count} empty mod asset files destroyed" + end + task mod_approval: :environment do puts "\nApproving all mods" unapproved_mods_count = Mod.where(approved: false).count diff --git a/mod-picker/public/resources/directives/imageUploader.html b/mod-picker/public/resources/directives/imageUploader.html deleted file mode 100644 index 806e258f9..000000000 --- a/mod-picker/public/resources/directives/imageUploader.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/mod-picker/public/resources/directives/layout/tabs.html b/mod-picker/public/resources/directives/layout/tabs.html index 7def37306..4cf4d046b 100644 --- a/mod-picker/public/resources/directives/layout/tabs.html +++ b/mod-picker/public/resources/directives/layout/tabs.html @@ -1,4 +1,4 @@ -
+
{{tab.name}} ({{tab.count}}) diff --git a/mod-picker/public/resources/directives/shared/pluginMetadata.html b/mod-picker/public/resources/directives/shared/pluginMetadata.html index 6b8e39afd..08f0f103b 100644 --- a/mod-picker/public/resources/directives/shared/pluginMetadata.html +++ b/mod-picker/public/resources/directives/shared/pluginMetadata.html @@ -1,6 +1,8 @@
Filename
-
{{plugin.filename}}
+
{{plugin.filename}} + ESM +