mirror of
https://github.com/kihashi/stardew_community_checklist.git
synced 2025-10-19 08:03:17 +00:00
Merge pull request #86 from kihashi/webpack
Update to Webpack and Vue Single File Components * Updates to a webpack based build * Splits application into single file components * Updates Bulma * Updates Vue * Adds support for mobile
This commit is contained in:
commit
95739821c3
12
.babelrc
Normal file
12
.babelrc
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
||||
}
|
||||
}],
|
||||
"stage-2"
|
||||
],
|
||||
"plugins": ["transform-vue-jsx", "transform-runtime"]
|
||||
}
|
||||
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
4
.eslintignore
Normal file
4
.eslintignore
Normal file
@ -0,0 +1,4 @@
|
||||
/build/
|
||||
/config/
|
||||
/dist/
|
||||
/*.js
|
||||
29
.eslintrc.js
Normal file
29
.eslintrc.js
Normal file
@ -0,0 +1,29 @@
|
||||
// https://eslint.org/docs/user-guide/configuring
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
extends: [
|
||||
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
|
||||
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
|
||||
'plugin:vue/essential',
|
||||
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
|
||||
'standard'
|
||||
],
|
||||
// required to lint *.vue files
|
||||
plugins: [
|
||||
'vue'
|
||||
],
|
||||
// add your custom rules here
|
||||
rules: {
|
||||
// allow async-await
|
||||
'generator-star-spacing': 'off',
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
}
|
||||
}
|
||||
74
.gitignore
vendored
74
.gitignore
vendored
@ -1,62 +1,14 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
#Ipython Notebook
|
||||
.ipynb_checkpoints
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
|
||||
10
.postcssrc.js
Normal file
10
.postcssrc.js
Normal file
@ -0,0 +1,10 @@
|
||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||
|
||||
module.exports = {
|
||||
"plugins": {
|
||||
"postcss-import": {},
|
||||
"postcss-url": {},
|
||||
// to edit target browsers: use "browserslist" field in package.json
|
||||
"autoprefixer": {}
|
||||
}
|
||||
}
|
||||
27
README.md
27
README.md
@ -1,12 +1,8 @@
|
||||
# Stardew Community Checklist
|
||||
|
||||
A checklist for the Community Center Bundles in Stardew Valley
|
||||
> A Checklist for the Community Center Bundles in Stardew Valley
|
||||
|
||||
SCC is an application for keeping track of the community center bundles in Stardew Valley. When I started playing the
|
||||
game, I spent a decent amount of time searching the wiki trying to figure out what items I needed for the community
|
||||
center and keeping track of which ones I had already turned in. I started working on this as a way to help myself out
|
||||
playing the game. Of course, I finished the community center bundles before I finished the site, but I figured that
|
||||
maybe someone else would get some use out of it.
|
||||
## Build Setup
|
||||
|
||||
NOTE: I am currently working on re-writing the app. The demo site (which is still missing functionality) is available and the code is on the webpack branch.
|
||||
|
||||
@ -15,10 +11,6 @@ NOTE: I am currently working on re-writing the app. The demo site (which is stil
|
||||
|
||||
A live version of the site is available at the following link:
|
||||
|
||||
---
|
||||
# http://www.stardewcommunitychecklist.com/
|
||||
---
|
||||
|
||||
Note: The layout makes pretty big use of [Flexbox](https://www.w3.org/TR/css-flexbox-1/), which is not quite finalized.
|
||||
I've tested the site in Chrome, Firefox, and Safari. IE seems to have
|
||||
[some problems with text layout](http://i.imgur.com/smeMuAi.png), though.
|
||||
@ -63,18 +55,3 @@ If you think of something, please, [make a post on the subreddit](https://www.re
|
||||
|
||||
SCC is a single page application, so all it needs is a web server. You can use any web server that you like, but I
|
||||
prefer to use the built-in python web server, which is available on any platform with Python installed.
|
||||
|
||||
```
|
||||
# Python 3.5
|
||||
python -m http.server
|
||||
```
|
||||
|
||||
Libraries and Frameworks used:
|
||||
|
||||
* [vuejs](http://vuejs.org/)
|
||||
* [Bulma](http://bulma.io/)
|
||||
|
||||
Feature requests and pull requests are certainly welcome. I still need to clean up a lot of things in the repository
|
||||
(For example, I changed naming styles part way through and the item "cards" need to be made into a vue component so they
|
||||
aren't repeated), but the code should *mostly* be easy to figure out. I suspect there are optimizations to be done in
|
||||
the searching and filtering logic as well.
|
||||
|
||||
41
build/build.js
Normal file
41
build/build.js
Normal file
@ -0,0 +1,41 @@
|
||||
'use strict'
|
||||
require('./check-versions')()
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
const ora = require('ora')
|
||||
const rm = require('rimraf')
|
||||
const path = require('path')
|
||||
const chalk = require('chalk')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const webpackConfig = require('./webpack.prod.conf')
|
||||
|
||||
const spinner = ora('building for production...')
|
||||
spinner.start()
|
||||
|
||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
||||
if (err) throw err
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
spinner.stop()
|
||||
if (err) throw err
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n\n')
|
||||
|
||||
if (stats.hasErrors()) {
|
||||
console.log(chalk.red(' Build failed with errors.\n'))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(chalk.cyan(' Build complete.\n'))
|
||||
console.log(chalk.yellow(
|
||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
))
|
||||
})
|
||||
})
|
||||
54
build/check-versions.js
Normal file
54
build/check-versions.js
Normal file
@ -0,0 +1,54 @@
|
||||
'use strict'
|
||||
const chalk = require('chalk')
|
||||
const semver = require('semver')
|
||||
const packageConfig = require('../package.json')
|
||||
const shell = require('shelljs')
|
||||
|
||||
function exec (cmd) {
|
||||
return require('child_process').execSync(cmd).toString().trim()
|
||||
}
|
||||
|
||||
const versionRequirements = [
|
||||
{
|
||||
name: 'node',
|
||||
currentVersion: semver.clean(process.version),
|
||||
versionRequirement: packageConfig.engines.node
|
||||
}
|
||||
]
|
||||
|
||||
if (shell.which('npm')) {
|
||||
versionRequirements.push({
|
||||
name: 'npm',
|
||||
currentVersion: exec('npm --version'),
|
||||
versionRequirement: packageConfig.engines.npm
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
const warnings = []
|
||||
|
||||
for (let i = 0; i < versionRequirements.length; i++) {
|
||||
const mod = versionRequirements[i]
|
||||
|
||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||
warnings.push(mod.name + ': ' +
|
||||
chalk.red(mod.currentVersion) + ' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
console.log('')
|
||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||
console.log()
|
||||
|
||||
for (let i = 0; i < warnings.length; i++) {
|
||||
const warning = warnings[i]
|
||||
console.log(' ' + warning)
|
||||
}
|
||||
|
||||
console.log()
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
BIN
build/logo.png
Normal file
BIN
build/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
101
build/utils.js
Normal file
101
build/utils.js
Normal file
@ -0,0 +1,101 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const config = require('../config')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const packageConfig = require('../package.json')
|
||||
|
||||
exports.assetsPath = function (_path) {
|
||||
const assetsSubDirectory = process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory
|
||||
|
||||
return path.posix.join(assetsSubDirectory, _path)
|
||||
}
|
||||
|
||||
exports.cssLoaders = function (options) {
|
||||
options = options || {}
|
||||
|
||||
const cssLoader = {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap
|
||||
}
|
||||
}
|
||||
|
||||
const postcssLoader = {
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap
|
||||
}
|
||||
}
|
||||
|
||||
// generate loader string to be used with extract text plugin
|
||||
function generateLoaders (loader, loaderOptions) {
|
||||
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
|
||||
|
||||
if (loader) {
|
||||
loaders.push({
|
||||
loader: loader + '-loader',
|
||||
options: Object.assign({}, loaderOptions, {
|
||||
sourceMap: options.sourceMap
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Extract CSS when that option is specified
|
||||
// (which is the case during production build)
|
||||
if (options.extract) {
|
||||
return ExtractTextPlugin.extract({
|
||||
use: loaders,
|
||||
fallback: 'vue-style-loader'
|
||||
})
|
||||
} else {
|
||||
return ['vue-style-loader'].concat(loaders)
|
||||
}
|
||||
}
|
||||
|
||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(),
|
||||
postcss: generateLoaders(),
|
||||
less: generateLoaders('less'),
|
||||
sass: generateLoaders('sass', { indentedSyntax: true }),
|
||||
scss: generateLoaders('sass'),
|
||||
stylus: generateLoaders('stylus'),
|
||||
styl: generateLoaders('stylus')
|
||||
}
|
||||
}
|
||||
|
||||
// Generate loaders for standalone style files (outside of .vue)
|
||||
exports.styleLoaders = function (options) {
|
||||
const output = []
|
||||
const loaders = exports.cssLoaders(options)
|
||||
|
||||
for (const extension in loaders) {
|
||||
const loader = loaders[extension]
|
||||
output.push({
|
||||
test: new RegExp('\\.' + extension + '$'),
|
||||
use: loader
|
||||
})
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
exports.createNotifierCallback = () => {
|
||||
const notifier = require('node-notifier')
|
||||
|
||||
return (severity, errors) => {
|
||||
if (severity !== 'error') return
|
||||
|
||||
const error = errors[0]
|
||||
const filename = error.file && error.file.split('!').pop()
|
||||
|
||||
notifier.notify({
|
||||
title: packageConfig.name,
|
||||
message: severity + ': ' + error.name,
|
||||
subtitle: filename || '',
|
||||
icon: path.join(__dirname, 'logo.png')
|
||||
})
|
||||
}
|
||||
}
|
||||
22
build/vue-loader.conf.js
Normal file
22
build/vue-loader.conf.js
Normal file
@ -0,0 +1,22 @@
|
||||
'use strict'
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const isProduction = process.env.NODE_ENV === 'production'
|
||||
const sourceMapEnabled = isProduction
|
||||
? config.build.productionSourceMap
|
||||
: config.dev.cssSourceMap
|
||||
|
||||
module.exports = {
|
||||
loaders: utils.cssLoaders({
|
||||
sourceMap: sourceMapEnabled,
|
||||
extract: isProduction
|
||||
}),
|
||||
cssSourceMap: sourceMapEnabled,
|
||||
cacheBusting: config.dev.cacheBusting,
|
||||
transformToRequire: {
|
||||
video: ['src', 'poster'],
|
||||
source: 'src',
|
||||
img: 'src',
|
||||
image: 'xlink:href'
|
||||
}
|
||||
}
|
||||
92
build/webpack.base.conf.js
Normal file
92
build/webpack.base.conf.js
Normal file
@ -0,0 +1,92 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const vueLoaderConfig = require('./vue-loader.conf')
|
||||
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
const createLintingRule = () => ({
|
||||
test: /\.(js|vue)$/,
|
||||
loader: 'eslint-loader',
|
||||
enforce: 'pre',
|
||||
include: [resolve('src'), resolve('test')],
|
||||
options: {
|
||||
formatter: require('eslint-friendly-formatter'),
|
||||
emitWarning: !config.dev.showEslintErrorsInOverlay
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
context: path.resolve(__dirname, '../'),
|
||||
entry: {
|
||||
app: './src/main.js'
|
||||
},
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: '[name].js',
|
||||
publicPath: process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsPublicPath
|
||||
: config.dev.assetsPublicPath
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.vue', '.json'],
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js',
|
||||
'@': resolve('src'),
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
...(config.dev.useEslint ? [createLintingRule()] : []),
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
options: vueLoaderConfig
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('img/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('media/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
node: {
|
||||
// prevent webpack from injecting useless setImmediate polyfill because Vue
|
||||
// source contains it (although only uses it if it's native).
|
||||
setImmediate: false,
|
||||
// prevent webpack from injecting mocks to Node native modules
|
||||
// that does not make sense for the client
|
||||
dgram: 'empty',
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty',
|
||||
child_process: 'empty'
|
||||
}
|
||||
}
|
||||
95
build/webpack.dev.conf.js
Executable file
95
build/webpack.dev.conf.js
Executable file
@ -0,0 +1,95 @@
|
||||
'use strict'
|
||||
const utils = require('./utils')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const merge = require('webpack-merge')
|
||||
const path = require('path')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
|
||||
const portfinder = require('portfinder')
|
||||
|
||||
const HOST = process.env.HOST
|
||||
const PORT = process.env.PORT && Number(process.env.PORT)
|
||||
|
||||
const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
|
||||
},
|
||||
// cheap-module-eval-source-map is faster for development
|
||||
devtool: config.dev.devtool,
|
||||
|
||||
// these devServer options should be customized in /config/index.js
|
||||
devServer: {
|
||||
clientLogLevel: 'warning',
|
||||
historyApiFallback: {
|
||||
rewrites: [
|
||||
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
|
||||
],
|
||||
},
|
||||
hot: true,
|
||||
contentBase: false, // since we use CopyWebpackPlugin.
|
||||
compress: true,
|
||||
host: HOST || config.dev.host,
|
||||
port: PORT || config.dev.port,
|
||||
open: config.dev.autoOpenBrowser,
|
||||
overlay: config.dev.errorOverlay
|
||||
? { warnings: false, errors: true }
|
||||
: false,
|
||||
publicPath: config.dev.assetsPublicPath,
|
||||
proxy: config.dev.proxyTable,
|
||||
quiet: true, // necessary for FriendlyErrorsPlugin
|
||||
watchOptions: {
|
||||
poll: config.dev.poll,
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': require('../config/dev.env')
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
// https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: 'index.html',
|
||||
inject: true
|
||||
}),
|
||||
// copy custom static assets
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, '../static'),
|
||||
to: config.dev.assetsSubDirectory,
|
||||
ignore: ['.*']
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
|
||||
module.exports = new Promise((resolve, reject) => {
|
||||
portfinder.basePort = process.env.PORT || config.dev.port
|
||||
portfinder.getPort((err, port) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
// publish the new Port, necessary for e2e tests
|
||||
process.env.PORT = port
|
||||
// add port to devServer config
|
||||
devWebpackConfig.devServer.port = port
|
||||
|
||||
// Add FriendlyErrorsPlugin
|
||||
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
|
||||
compilationSuccessInfo: {
|
||||
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
|
||||
},
|
||||
onErrors: config.dev.notifyOnErrors
|
||||
? utils.createNotifierCallback()
|
||||
: undefined
|
||||
}))
|
||||
|
||||
resolve(devWebpackConfig)
|
||||
}
|
||||
})
|
||||
})
|
||||
145
build/webpack.prod.conf.js
Normal file
145
build/webpack.prod.conf.js
Normal file
@ -0,0 +1,145 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const utils = require('./utils')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const merge = require('webpack-merge')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
|
||||
|
||||
const env = require('../config/prod.env')
|
||||
|
||||
const webpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
extract: true,
|
||||
usePostCSS: true
|
||||
})
|
||||
},
|
||||
devtool: config.build.productionSourceMap ? config.build.devtool : false,
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
||||
},
|
||||
plugins: [
|
||||
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
},
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
parallel: true
|
||||
}),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash].css'),
|
||||
// Setting the following option to `false` will not extract CSS from codesplit chunks.
|
||||
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
|
||||
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
|
||||
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
|
||||
allChunks: true,
|
||||
}),
|
||||
// Compress extracted CSS. We are using this plugin so that possible
|
||||
// duplicated CSS from different components can be deduped.
|
||||
new OptimizeCSSPlugin({
|
||||
cssProcessorOptions: config.build.productionSourceMap
|
||||
? { safe: true, map: { inline: false } }
|
||||
: { safe: true }
|
||||
}),
|
||||
// generate dist index.html with correct asset hash for caching.
|
||||
// you can customize output by editing /index.html
|
||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: config.build.index,
|
||||
template: 'index.html',
|
||||
inject: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true
|
||||
// more options:
|
||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
||||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'dependency'
|
||||
}),
|
||||
// keep module.id stable when vendor modules does not change
|
||||
new webpack.HashedModuleIdsPlugin(),
|
||||
// enable scope hoisting
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
// split vendor js into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks (module) {
|
||||
// any required modules inside node_modules are extracted to vendor
|
||||
return (
|
||||
module.resource &&
|
||||
/\.js$/.test(module.resource) &&
|
||||
module.resource.indexOf(
|
||||
path.join(__dirname, '../node_modules')
|
||||
) === 0
|
||||
)
|
||||
}
|
||||
}),
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
minChunks: Infinity
|
||||
}),
|
||||
// This instance extracts shared chunks from code splitted chunks and bundles them
|
||||
// in a separate chunk, similar to the vendor chunk
|
||||
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'app',
|
||||
async: 'vendor-async',
|
||||
children: true,
|
||||
minChunks: 3
|
||||
}),
|
||||
|
||||
// copy custom static assets
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, '../static'),
|
||||
to: config.build.assetsSubDirectory,
|
||||
ignore: ['.*']
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
|
||||
if (config.build.productionGzip) {
|
||||
const CompressionWebpackPlugin = require('compression-webpack-plugin')
|
||||
|
||||
webpackConfig.plugins.push(
|
||||
new CompressionWebpackPlugin({
|
||||
asset: '[path].gz[query]',
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp(
|
||||
'\\.(' +
|
||||
config.build.productionGzipExtensions.join('|') +
|
||||
')$'
|
||||
),
|
||||
threshold: 10240,
|
||||
minRatio: 0.8
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (config.build.bundleAnalyzerReport) {
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
||||
7
config/dev.env.js
Normal file
7
config/dev.env.js
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict'
|
||||
const merge = require('webpack-merge')
|
||||
const prodEnv = require('./prod.env')
|
||||
|
||||
module.exports = merge(prodEnv, {
|
||||
NODE_ENV: '"development"'
|
||||
})
|
||||
76
config/index.js
Normal file
76
config/index.js
Normal file
@ -0,0 +1,76 @@
|
||||
'use strict'
|
||||
// Template version: 1.3.1
|
||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
dev: {
|
||||
|
||||
// Paths
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
proxyTable: {},
|
||||
|
||||
// Various Dev Server settings
|
||||
host: 'localhost', // can be overwritten by process.env.HOST
|
||||
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||
autoOpenBrowser: false,
|
||||
errorOverlay: true,
|
||||
notifyOnErrors: true,
|
||||
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
|
||||
|
||||
// Use Eslint Loader?
|
||||
// If true, your code will be linted during bundling and
|
||||
// linting errors and warnings will be shown in the console.
|
||||
useEslint: true,
|
||||
// If true, eslint errors and warnings will also be shown in the error overlay
|
||||
// in the browser.
|
||||
showEslintErrorsInOverlay: false,
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
// https://webpack.js.org/configuration/devtool/#development
|
||||
devtool: 'cheap-module-eval-source-map',
|
||||
|
||||
// If you have problems debugging vue-files in devtools,
|
||||
// set this to false - it *may* help
|
||||
// https://vue-loader.vuejs.org/en/options.html#cachebusting
|
||||
cacheBusting: true,
|
||||
|
||||
cssSourceMap: true
|
||||
},
|
||||
|
||||
build: {
|
||||
// Template for index.html
|
||||
index: path.resolve(__dirname, '../dist/index.html'),
|
||||
|
||||
// Paths
|
||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
productionSourceMap: true,
|
||||
// https://webpack.js.org/configuration/devtool/#production
|
||||
devtool: '#source-map',
|
||||
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
// Surge or Netlify already gzip all static assets for you.
|
||||
// Before setting to `true`, make sure to:
|
||||
// npm install --save-dev compression-webpack-plugin
|
||||
productionGzip: false,
|
||||
productionGzipExtensions: ['js', 'css'],
|
||||
|
||||
// Run the build command with an extra argument to
|
||||
// View the bundle analyzer report after build finishes:
|
||||
// `npm run build --report`
|
||||
// Set to `true` or `false` to always turn it on or off
|
||||
bundleAnalyzerReport: process.env.npm_config_report
|
||||
}
|
||||
}
|
||||
4
config/prod.env.js
Normal file
4
config/prod.env.js
Normal file
@ -0,0 +1,4 @@
|
||||
'use strict'
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
BIN
favicon.ico
BIN
favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
639
index.html
639
index.html
@ -1,630 +1,13 @@
|
||||
<!doctype HTML>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Stardew Valley Community Checklist</title>
|
||||
<link type="text/css" rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css"/>
|
||||
<link type="text/css" rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"/>
|
||||
<link type="text/css" rel="stylesheet" href="main.css"/>
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<section class="hero is-info">
|
||||
<div class="hero-head">
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a href="./" class="navbar-item"><h1 class="title">Stardew Community Checklist</h1></a>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-end">
|
||||
<span class="navbar-item">
|
||||
<a href="#" id="save-button" class="button is-light is-outlined" v-on:click.stop="enterSaveMode">
|
||||
<span class="icon"><i class="fa fa-download"></i></span>
|
||||
<span>Export Data</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="navbar-item">
|
||||
<a href="#" id="load-button" class="button is-light is-outlined" v-on:click.stop="enterLoadMode">
|
||||
<span class="icon"><i class="fa fa-upload"></i></span>
|
||||
<span>Import Data</span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
<nav class="navbar has-shadow">
|
||||
<div class="container">
|
||||
<div class="navbar-tabs">
|
||||
<a id="bundles-nav" class="navbar-item is-tab" href="#" v-on:click.stop="change_page('bundles')"
|
||||
v-bind:class="['bundles' == active_page ? 'is-active' : '']">
|
||||
Bundles
|
||||
</a>
|
||||
<a id="ab-nav" class="navbar-item is-tab" href="#" v-on:click.stop="change_page('ab-list')"
|
||||
v-bind:class="['ab-list' == active_page ? 'is-active' : '']">
|
||||
Alphabetical
|
||||
</a>
|
||||
<a id="seasons-nav" class="navbar-item is-tab" href="#" v-on:click.stop="change_page('seasons')"
|
||||
v-bind:class="['seasons' == active_page ? 'is-active' : '']">
|
||||
Seasons
|
||||
</a>
|
||||
<a id="skills-nav" class="navbar-item is-tab" href="#" v-on:click.stop="change_page('skills')"
|
||||
v-bind:class="['skills' == active_page ? 'is-active' : '']">
|
||||
Skills
|
||||
</a>
|
||||
<a id="change-nav" class="navbar-item is-tab" href="#" v-on:click.stop="change_page('changelog')"
|
||||
v-bind:class="['changelog' == active_page ? 'is-active' : '']">
|
||||
Change Log
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-end">
|
||||
<span class="navbar-item">
|
||||
<a class="button" v-on:click="toggleHideCompleted">
|
||||
<span class="icon">
|
||||
<i class="fa" v-bind:class="[hideCompleted ? 'fa-check-square-o' : 'fa-square-o']"></i>
|
||||
</span>
|
||||
<span>
|
||||
Hide Completed
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="navbar-item">
|
||||
<div class="buttons has-addons">
|
||||
<a class="button" v-on:click="toggleHideSpoilers">
|
||||
<span class="icon">
|
||||
<i class="fa" v-bind:class="[hideSpoilers ? 'fa-check-square-o' : 'fa-square-o']"></i>
|
||||
</span>
|
||||
<span>
|
||||
Hide Spoilers
|
||||
</span>
|
||||
</a>
|
||||
<a class="button is-info" v-on:click="enterSpoilerSettings">
|
||||
<span class="icon">
|
||||
<i class="fa fa-cogs"></i>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Save Modal -->
|
||||
<div id="save-model" class="modal" v-bind:class="[save_mode ? 'is-active' : '']">
|
||||
<div class="modal-background" v-on:click="exitSaveMode"></div>
|
||||
<div class="modal-container">
|
||||
<div class="modal-content">
|
||||
<div class="box">
|
||||
<div class="notification is-success">
|
||||
Your data has been saved locally. This data string is provided in case you want to make a backup or
|
||||
take your data to another computer.
|
||||
</div>
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input id="user-data-serialized" readonly class="input" type="text" placeholder="Save Data"
|
||||
v-bind:value="user_data_serialized">
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-info copy" data-clipboard-target="#user-data-serialized">
|
||||
<span class="icon">
|
||||
<i class="fa fa-clipboard"></i>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="modal-close" v-on:click="exitSaveMode"></button>
|
||||
</div>
|
||||
|
||||
<!-- Load Modal -->
|
||||
<div id="load-model" class="modal" v-bind:class="[load_mode ? 'is-active' : '']">
|
||||
<div class="modal-background" v-on:click="exitLoadMode"></div>
|
||||
<div class="modal-container">
|
||||
<div class="modal-content">
|
||||
<div class="box">
|
||||
<div class="notification is-warning">
|
||||
If you previously saved your data on this computer, it should already be loaded. This utility is
|
||||
only for loading a data string from a backup or another computer.
|
||||
</div>
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input class="input" type="text" placeholder="Load Data" v-model="enteredData">
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-info" v-on:click="loadData(enteredData)">
|
||||
Load Data
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="modal-close" v-on:click="exitLoadMode"></button>
|
||||
</div>
|
||||
|
||||
<!-- Spoilers Settings Modal -->
|
||||
<div id="spoilers-modal" class="modal" v-bind:class="[pick_spoilers ? 'is-active' : '']">
|
||||
<div class="modal-background" v-on:click="exitSpoilerSettings"></div>
|
||||
<div class="modal-container">
|
||||
<div class="modal-content">
|
||||
<div class="box">
|
||||
<div class="content">
|
||||
<p class="notification is-info">
|
||||
These settings control which elements are hidden when Hide Spoilers is enabled.
|
||||
</p>
|
||||
<p class="control">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-model="temp_spoilers.bundle_rewards">
|
||||
Bundle Rewards
|
||||
</label>
|
||||
</p>
|
||||
<p class="control">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-model="temp_spoilers.item_source">
|
||||
Item Source Information
|
||||
</label>
|
||||
</p>
|
||||
<p class="control">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-model="temp_spoilers.item_seasons">
|
||||
Item Seasons
|
||||
</label>
|
||||
</p>
|
||||
<p class="control">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-model="temp_spoilers.item_skills">
|
||||
Item Skills
|
||||
</label>
|
||||
</p>
|
||||
<a class="button is-info is-pulled-right" v-on:click="saveSpoilerSettings">
|
||||
<span class="icon">
|
||||
<i class="fa fa-save"></i>
|
||||
</span>
|
||||
<span>
|
||||
Save
|
||||
</span>
|
||||
</a>
|
||||
<div class="is-clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="modal-close" v-on:click="exitSpoilerSettings"></button>
|
||||
</div>
|
||||
|
||||
<!-- BUNDLE TAB -->
|
||||
<section id="bundle-section" class="section" v-if="active_page == 'bundles' && static !== null">
|
||||
<div class="container is-fluid is-marginless">
|
||||
<div class="columns">
|
||||
<div class="column is-2 is-paddingless">
|
||||
<nav class="panel">
|
||||
<p class="panel-heading">
|
||||
Bundles
|
||||
</p>
|
||||
<p class="panel-tabs is-size-7">
|
||||
<a href="#" v-for="room in static.rooms" v-bind:id="'panel-room-' + room.id"
|
||||
class="has-text-centered"
|
||||
v-bind:class="[room.id == active_room ? 'is-active' : '']"
|
||||
v-on:click.stop="change_room(room.id)">
|
||||
{{ room.name }}
|
||||
</a>
|
||||
</p>
|
||||
<template v-for="bundle in active_room_bundles">
|
||||
<a class="panel-block" href="#"
|
||||
v-bind:id="'panel-bundle-' + bundle.id" v-bind:class="[bundle.id == active_bundle ? 'is-active' : '']"
|
||||
v-on:click.stop="change_bundle(bundle.id)" v-if="!(hideCompleted && isBundleComplete(bundle.id))">
|
||||
|
||||
<span class="panel-icon">
|
||||
<i class="fa fa-archive"></i>
|
||||
</span>
|
||||
<span v-bind:class="[isBundleComplete(bundle.id) ? 'bundle-complete' : '']">{{ bundle.name }}</span>
|
||||
</a>
|
||||
</template>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h3 class="title">
|
||||
{{ static.bundles[active_bundle].name }}
|
||||
<span class="is-pulled-right">
|
||||
{{ user_data[active_bundle].length }} / {{ static.bundles[active_bundle].items_required }}
|
||||
</span>
|
||||
</h3>
|
||||
<h5 class="subtitle" v-if="!(hideSpoilers && spoilers.bundle_rewards)">{{ static.bundles[active_bundle].reward }}</h5>
|
||||
<h5 class="subtitle" v-else> </h5>
|
||||
<progress class="progress is-info"
|
||||
v-bind:value="user_data[active_bundle].length"
|
||||
v-bind:max="static.bundles[active_bundle].items_required"></progress>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3 class="title">
|
||||
{{ static.rooms[static.bundles[active_bundle].room].name }}
|
||||
<span class="is-pulled-right">
|
||||
{{ getRoomItemsChecked(static.bundles[active_bundle].room) }} / {{ getRoomItemsRequired(static.bundles[active_bundle].room) }}
|
||||
</span>
|
||||
</h3>
|
||||
<h5 class="subtitle">{{ static.rooms[static.bundles[active_bundle].room].reward }}</h5>
|
||||
<progress class="progress is-info"
|
||||
v-bind:value="getRoomItemsChecked(static.bundles[active_bundle].room)"
|
||||
v-bind:max="getRoomItemsRequired(static.bundles[active_bundle].room)"
|
||||
>
|
||||
|
||||
</progress>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns is-multiline">
|
||||
<template v-for="item in active_bundle_items">
|
||||
<div class="column is-3 is-flex" v-if="!(hideCompleted && isCompleted(item))">
|
||||
<div class="card is-fullwidth is-flex eq-line">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
{{ item.name }}
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content eq-line is-flex">
|
||||
<div class="content is-flex">
|
||||
<div class="columns source">
|
||||
<div class="column">
|
||||
<div v-if="!(hideSpoilers && spoilers.item_source)">{{ item.source }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="control">
|
||||
<a class="button is-fullwidth" v-for="(bundle_id, index) in item.bundles"
|
||||
v-on:click="toggleItemInBundle(bundle_id, item.id, index)"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'is-success' : '',
|
||||
!isItemInBundle(bundle_id, item.id, index) && !isBundleComplete(bundle_id) ? 'is-danger' : '' ]">
|
||||
<span class="icon">
|
||||
<i class="fa"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'fa-check-square-o' : 'fa-square-o']"></i>
|
||||
</span>
|
||||
<span>{{ static.bundles[bundle_id].name }}</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_seasons)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-calendar-check-o"></i></span>
|
||||
<span class="tag is-primary is-text-centered is-rounded"
|
||||
v-for="season in getItemSeasons(item)">
|
||||
{{ season.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_skills)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-tree"></i></span>
|
||||
<span class="tag is-info is-text-centered is-rounded"
|
||||
v-for="skill in getItemSkills(item)">
|
||||
{{ skill.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- AB TAB -->
|
||||
<section id="ab-section" class="section" v-if="active_page == 'ab-list' && static !== null">
|
||||
<div class="container is-fluid is-marginless">
|
||||
<div class="columns">
|
||||
<div class="column is-4">
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Search</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<input class="input" type="text" placeholder="Search" v-model="search_term">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="columns is-multiline">
|
||||
<template v-for="item in filtered_items">
|
||||
<div class="column is-3 is-flex" v-if="!(hideCompleted && isCompleted(item))">
|
||||
<div class="card is-fullwidth is-flex eq-line">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
{{ item.name }}
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content eq-line is-flex">
|
||||
<div class="content is-flex">
|
||||
<div class="columns source">
|
||||
<div class="column">
|
||||
<div v-if="!(hideSpoilers && spoilers.item_source)">{{ item.source }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="control">
|
||||
<a class="button is-fullwidth" v-for="(bundle_id, index) in item.bundles"
|
||||
v-on:click="toggleItemInBundle(bundle_id, item.id, index)"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'is-success' : '',
|
||||
!isItemInBundle(bundle_id, item.id, index) && !isBundleComplete(bundle_id) ? 'is-danger' : '' ]">
|
||||
<span class="icon">
|
||||
<i class="fa"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'fa-check-square-o' : 'fa-square-o']"></i>
|
||||
</span>
|
||||
<span>{{ static.bundles[bundle_id].name }}</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_seasons)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-calendar-check-o"></i></span>
|
||||
<span class="tag is-primary is-text-centered is-rounded"
|
||||
v-for="season in getItemSeasons(item)">
|
||||
{{ season.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_skills)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-tree"></i></span>
|
||||
<span class="tag is-info is-text-centered is-rounded"
|
||||
v-for="skill in getItemSkills(item)">
|
||||
{{ skill.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Seasons Tab -->
|
||||
<section id="seasons-tab" class="section" v-if="active_page == 'seasons'">
|
||||
<div class="container is-fluid is-marginless">
|
||||
<div class="columns">
|
||||
<div class="column is-2">
|
||||
<nav class="panel">
|
||||
<p class="panel-heading">
|
||||
Seasons
|
||||
</p>
|
||||
<a class="panel-block" href="#" v-for="season in static.seasons" v-bind:id="'panel-season-' + season.id"
|
||||
v-bind:class="[season.id == active_season ? 'is-active' : '']"
|
||||
v-on:click.stop="change_season(season.id)">
|
||||
<span class="panel-icon">
|
||||
<i class="fa fa-calendar"></i>
|
||||
</span> {{ season.name }}
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3 class="title">{{ getSeasonName(active_season) }}</h3>
|
||||
<progress class="progress is-info" value="" max=""></progress>
|
||||
<div class="columns is-multiline">
|
||||
<template v-for="item in active_season_items">
|
||||
<div class="column is-3 is-flex" v-if="!(hideCompleted && isCompleted(item))">
|
||||
<div class="card is-fullwidth is-flex eq-line">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
{{ item.name }}
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content eq-line is-flex">
|
||||
<div class="content is-flex">
|
||||
<div class="columns source">
|
||||
<div class="column">
|
||||
<div v-if="!(hideSpoilers && spoilers.item_source)">{{ item.source }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="control">
|
||||
<a class="button is-fullwidth" v-for="(bundle_id, index) in item.bundles"
|
||||
v-on:click="toggleItemInBundle(bundle_id, item.id, index)"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'is-success' : '',
|
||||
!isItemInBundle(bundle_id, item.id, index) && !isBundleComplete(bundle_id) ? 'is-danger' : '' ]">
|
||||
<span class="icon">
|
||||
<i class="fa"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'fa-check-square-o' : 'fa-square-o']"></i>
|
||||
</span>
|
||||
<span>{{ static.bundles[bundle_id].name }}</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_seasons)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-calendar-check-o"></i></span>
|
||||
<span class="tag is-primary is-text-centered is-rounded"
|
||||
v-for="season in getItemSeasons(item)">
|
||||
{{ season.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_skills)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-tree"></i></span>
|
||||
<span class="tag is-info is-text-centered is-rounded"
|
||||
v-for="skill in getItemSkills(item)">
|
||||
{{ skill.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Skills Tab -->
|
||||
<section id="skills-tab" class="section" v-if="active_page == 'skills'">
|
||||
<div class="container is-fluid is-marginless">
|
||||
<div class="columns">
|
||||
<div class="column is-2">
|
||||
<nav class="panel">
|
||||
<p class="panel-heading">
|
||||
Skills
|
||||
</p>
|
||||
<a class="panel-block" href="#" v-for="skill in static.skills" v-bind:id="'panel-skill-' + skill.id"
|
||||
v-bind:class="[skill.id == active_skill ? 'is-active' : '']"
|
||||
v-on:click.stop="change_skill(skill.id)">
|
||||
<span class="panel-icon">
|
||||
<i class="fa fa-tree"></i>
|
||||
</span> {{ skill.name }}
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3 class="title">{{ getSkillName(active_skill) }}</h3>
|
||||
<progress class="progress is-info" value="" max=""></progress>
|
||||
<div class="columns is-multiline">
|
||||
<template v-for="item in active_skill_items">
|
||||
<div class="column is-3 is-flex" v-if="!(hideCompleted && isCompleted(item))">
|
||||
<div class="card is-fullwidth is-flex eq-line">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
{{ item.name }}
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content eq-line is-flex">
|
||||
<div class="content is-flex">
|
||||
<div class="columns source">
|
||||
<div class="column">
|
||||
<div v-if="!(hideSpoilers && spoilers.item_source)">{{ item.source }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="control">
|
||||
<a class="button is-fullwidth" v-for="(bundle_id, index) in item.bundles"
|
||||
v-on:click="toggleItemInBundle(bundle_id, item.id, index)"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'is-success' : '',
|
||||
!isItemInBundle(bundle_id, item.id, index) && !isBundleComplete(bundle_id) ? 'is-danger' : '' ]">
|
||||
<span class="icon">
|
||||
<i class="fa"
|
||||
v-bind:class="[isItemInBundle(bundle_id, item.id, index) ? 'fa-check-square-o' : 'fa-square-o']"></i>
|
||||
</span>
|
||||
<span>{{ static.bundles[bundle_id].name }}</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_seasons)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-calendar-check-o"></i></span>
|
||||
<span class="tag is-primary is-text-centered is-rounded"
|
||||
v-for="season in getItemSeasons(item)">
|
||||
{{ season.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
<footer class="card-footer" v-if="!(hideSpoilers && spoilers.item_skills)">
|
||||
<div class="card-footer-item">
|
||||
<span class="icon is-small"><i class="fa fa-tree"></i></span>
|
||||
<span class="tag is-info is-text-centered is-rounded"
|
||||
v-for="skill in getItemSkills(item)">
|
||||
{{ skill.name }}
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" v-if="active_page == 'changelog'">
|
||||
<div class="container">
|
||||
<h1 class="title">Change Log</h1>
|
||||
<div class="card is-fullwidth" v-for="version in changelog">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
{{ version.id }}
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<ul>
|
||||
<li v-for="change in version.changes">{{ change }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<p class="card-footer-item">
|
||||
Release Date: {{ version.date }}
|
||||
</p>
|
||||
<a v-bind:href="'https://github.com/kihashi/stardew_community_checklist/releases/tag/' + version.link" class="card-footer-item">
|
||||
<span class="icon">
|
||||
<i class="fa fa-github-square" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span>
|
||||
Github Release
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
<strong>Stardew Community Checklist</strong> by <a href="http://johncleaver.com">John Cleaver</a>. The source code is licensed
|
||||
<a href="http://opensource.org/licenses/mit-license.php">MIT</a>.
|
||||
</p>
|
||||
<p>
|
||||
Bundle and Item information is from the <a href="http://stardewvalleywiki.com/Stardew_Valley_Wiki">Stardew Valley Wiki</a>
|
||||
and is used under the <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0 License</a>.
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://stardewvalley.net/">Stardew Valley</a> © <a href="">Chucklefish LTD</a>.
|
||||
Developed by <a href="https://twitter.com/ConcernedApe">ConcernedApe</a>.
|
||||
</p>
|
||||
<p>
|
||||
<a class="icon" href="https://github.com/kihashi/stardew_community_checklist">
|
||||
<i class="fa fa-github"></i>
|
||||
</a>
|
||||
<a class="icon" href="https://www.reddit.com/r/StardewValley/comments/4ell1b/stardew_community_checklist_a_site_to_keep_track/">
|
||||
<i class="fa fa-reddit"></i>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Javascript -->
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue-resource@1.3.5"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/clipboard@1/dist/clipboard.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>
|
||||
<script type="text/javascript" src="main.js"></script>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="shortcut icon" type="image/png" href="/static/favicon.png"/>
|
||||
<title>Stardew Community Checklist</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
32
main.css
32
main.css
@ -1,32 +0,0 @@
|
||||
.eq-line {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.column.is-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.card {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.card-content{
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-footer-item{
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.button{
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.panel-tabs a {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.bundle-complete {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
279
main.js
279
main.js
@ -1,279 +0,0 @@
|
||||
var v = new Vue({
|
||||
el: '#app',
|
||||
data:{
|
||||
changelog: null,
|
||||
static: null,
|
||||
user_data: [],
|
||||
search_term: "",
|
||||
enteredData: "",
|
||||
active_page: "bundles",
|
||||
active_room: 0,
|
||||
active_bundle: 0,
|
||||
active_season: "spring",
|
||||
active_skill: "farming",
|
||||
save_mode: false,
|
||||
load_mode: false,
|
||||
pick_spoilers: false,
|
||||
hideCompleted: false,
|
||||
hideSpoilers: false,
|
||||
spoilers: {
|
||||
bundle_rewards: true,
|
||||
item_source: true,
|
||||
item_seasons: true,
|
||||
item_skills: true
|
||||
},
|
||||
temp_spoilers: {}
|
||||
|
||||
},
|
||||
beforeMount: function(){
|
||||
this.fetchData();
|
||||
this.fetchChangeLog();
|
||||
new Clipboard('.copy');
|
||||
storedUserData = localStorage.getItem('user_data');
|
||||
if(storedUserData !== null && storedUserData !== ""){
|
||||
this.loadData(storedUserData);
|
||||
}
|
||||
spoilers = localStorage.getItem('spoilers');
|
||||
if(spoilers !== null && spoilers !== ""){
|
||||
this.spoilers = JSON.parse(spoilers);
|
||||
}
|
||||
hideCompleted = localStorage.getItem('hideCompleted');
|
||||
if(hideCompleted !== null && hideCompleted !== ""){
|
||||
this.hideCompleted = JSON.parse(hideCompleted);
|
||||
}
|
||||
hideSpoilers = localStorage.getItem('hideSpoilers');
|
||||
if(hideSpoilers !== null && hideSpoilers !== ""){
|
||||
this.hideSpoilers = JSON.parse(hideSpoilers);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
user_data_serialized: function(){
|
||||
return btoa(JSON.stringify(this.user_data));
|
||||
},
|
||||
active_room_bundles: function(){
|
||||
var self = this;
|
||||
return this.static.bundles.filter(function(bundle){ return bundle.room === self.active_room });
|
||||
},
|
||||
active_bundle_items: function(){
|
||||
var self = this;
|
||||
return this.static.items.filter(function(item){ return item.bundles.indexOf(self.active_bundle) > -1});
|
||||
},
|
||||
active_season_items: function() {
|
||||
var self = this;
|
||||
if (self.active_season === self.static.seasons[0].id){
|
||||
return _.orderBy(
|
||||
this.static.items.filter(
|
||||
function(item){
|
||||
return item.seasons.length === 4;
|
||||
}
|
||||
),
|
||||
'name'
|
||||
)
|
||||
|
||||
}
|
||||
else {
|
||||
return _.orderBy(
|
||||
this.static.items.filter(
|
||||
function (item) {
|
||||
return item.seasons.indexOf(self.active_season) > -1
|
||||
}
|
||||
),
|
||||
'name'
|
||||
)
|
||||
}
|
||||
},
|
||||
active_skill_items: function() {
|
||||
var self = this;
|
||||
return _.orderBy(
|
||||
this.static.items.filter(
|
||||
function(item){
|
||||
return item.skills.indexOf(self.active_skill) > -1
|
||||
}
|
||||
),
|
||||
'name'
|
||||
)
|
||||
},
|
||||
filtered_items: function(){
|
||||
var self = this;
|
||||
return _.orderBy(self.static.items.filter(function(item){ return item.name.toLowerCase().indexOf(self.search_term.toLowerCase()) !== -1 }), 'name');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchData: function(){
|
||||
this.$http.get('bundles.json').then(function(response) {
|
||||
this.static = response.body;
|
||||
if(this.user_data.length <= 0){
|
||||
for(i=0; i<this.static.bundles.length;i++){
|
||||
this.user_data.push([]);
|
||||
}
|
||||
};
|
||||
}, function(response) {
|
||||
console.log("error fetching bundle data");
|
||||
});
|
||||
|
||||
},
|
||||
fetchChangeLog: function() {
|
||||
this.$http.get('changelog.json').then(function(response) {
|
||||
this.changelog = response.body.versions;
|
||||
}, function(response) {
|
||||
console.log("error fetching change log data");
|
||||
});
|
||||
},
|
||||
enterLoadMode: function(){
|
||||
this.load_mode = true;
|
||||
},
|
||||
exitLoadMode: function(){
|
||||
this.load_mode = false;
|
||||
},
|
||||
loadData: function(data){
|
||||
this.user_data = JSON.parse(atob(data));
|
||||
this.exitLoadMode();
|
||||
},
|
||||
enterSaveMode: function(){
|
||||
this.save_mode = true;
|
||||
localStorage.setItem('user_data', this.user_data_serialized);
|
||||
},
|
||||
exitSaveMode: function(){
|
||||
this.save_mode = false;
|
||||
},
|
||||
enterSpoilerSettings: function(){
|
||||
this.temp_spoilers = JSON.parse(JSON.stringify(this.spoilers));
|
||||
this.pick_spoilers = true;
|
||||
},
|
||||
saveSpoilerSettings: function(){
|
||||
this.spoilers = JSON.parse(JSON.stringify(this.temp_spoilers));
|
||||
localStorage.setItem('spoilers', JSON.stringify(this.spoilers));
|
||||
this.exitSpoilerSettings();
|
||||
},
|
||||
exitSpoilerSettings: function(){
|
||||
this.pick_spoilers = false
|
||||
},
|
||||
change_page: function(new_page){
|
||||
this.active_page = new_page;
|
||||
},
|
||||
change_bundle: function(new_bundle){
|
||||
this.active_bundle = new_bundle;
|
||||
},
|
||||
change_room: function(new_room){
|
||||
this.active_room = new_room;
|
||||
},
|
||||
change_season: function(new_season){
|
||||
this.active_season = new_season;
|
||||
},
|
||||
change_skill: function(new_skill){
|
||||
this.active_skill = new_skill;
|
||||
},
|
||||
toggleHideCompleted: function(){
|
||||
this.hideCompleted = !this.hideCompleted;
|
||||
localStorage.setItem('hideCompleted', JSON.stringify(this.hideCompleted));
|
||||
},
|
||||
toggleHideSpoilers: function(){
|
||||
this.hideSpoilers = !this.hideSpoilers;
|
||||
localStorage.setItem('hideSpoilers', JSON.stringify(this.hideSpoilers));
|
||||
},
|
||||
addItemToBundle: function(bundleId, itemId, itemPosition){
|
||||
this.user_data[bundleId].push({item: itemId, position: itemPosition});
|
||||
},
|
||||
removeItemFromBundle: function(bundleId, itemId, itemPosition){
|
||||
for(i = 0; i < this.user_data[bundleId].length; i++){
|
||||
if(this.user_data[bundleId][i].item === itemId && this.user_data[bundleId][i].position === itemPosition){
|
||||
this.user_data[bundleId].splice(i, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
toggleItemInBundle: function(bundleId, itemId, itemPosition){
|
||||
if(this.isItemInBundle(bundleId, itemId, itemPosition)){
|
||||
this.removeItemFromBundle(bundleId, itemId, itemPosition);
|
||||
}
|
||||
else{
|
||||
this.addItemToBundle(bundleId, itemId, itemPosition);
|
||||
}
|
||||
localStorage.setItem('user_data', this.user_data_serialized);
|
||||
},
|
||||
isItemInBundle: function(bundleId, itemId, itemPosition){
|
||||
if(this.user_data[bundleId].filter(function(element){
|
||||
return element.item === itemId && element.position === itemPosition;
|
||||
}).length > 0){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
getSeasonName: function(seasonId){
|
||||
for(i = 0; i < this.static.seasons.length; i++){
|
||||
if(this.static.seasons[i].id === seasonId){
|
||||
return this.static.seasons[i].name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
getSkillName: function(skillId){
|
||||
for(i = 0; i < this.static.skills.length; i++){
|
||||
if(this.static.skills[i].id === skillId){
|
||||
return this.static.skills[i].name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
getRoomItemsRequired: function(roomId) {
|
||||
return this.static.bundles.reduce(function(previousValue, nextValue){
|
||||
if(nextValue.room === roomId){
|
||||
return previousValue + nextValue.items_required;
|
||||
}
|
||||
else{
|
||||
return previousValue;
|
||||
}
|
||||
}, 0)
|
||||
},
|
||||
getRoomItemsChecked: function(roomId){
|
||||
var self = this;
|
||||
return this.static.bundles
|
||||
.filter(function(b){ return b.room === roomId; })
|
||||
.reduce(function(p, c){ return p + Math.min(self.user_data[c.id].length, c.items_required); }, 0);
|
||||
},
|
||||
isCompleted: function (item) {
|
||||
for(i=0; i < item.bundles.length; i++){
|
||||
if(!(this.isItemInBundle(item.bundles[i], item.id, i) || this.isBundleComplete(item.bundles[i]))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
isBundleComplete: function(bundle_id){
|
||||
return this.user_data[bundle_id].length >= this.static.bundles[bundle_id].items_required;
|
||||
},
|
||||
getItemSeasons: function(item){
|
||||
return this.static.seasons.filter(function(season){ return item.seasons.indexOf(season.id) > -1 });
|
||||
},
|
||||
getItemSkills: function(item){
|
||||
return this.static.skills.filter(function(skill){ return item.skills.indexOf(skill.id) > -1 });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.filter('inBundle', function(value, id){
|
||||
return value.filter(function(element){
|
||||
if(element.bundles.indexOf(id) > -1){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Vue.filter('seasonFilter', function(items, season_id){
|
||||
return items.filter(function(element){
|
||||
if(season_id == "allseasons" && element.seasons.length > 3){
|
||||
return true;
|
||||
}
|
||||
else if(element.seasons.length < 4 && element.seasons.indexOf(season_id) > -1){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
84
package.json
Normal file
84
package.json
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
"name": "stardew_community_checklist",
|
||||
"version": "1.0.0",
|
||||
"description": "A Checklist for the Community Center Bundles in Stardew Valley",
|
||||
"author": "John Cleaver <cleaver.john.k@gmail.com>",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
||||
"start": "npm run dev",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"build": "node build/build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome": "^1.1.4",
|
||||
"@fortawesome/fontawesome-free-brands": "^5.0.7",
|
||||
"@fortawesome/fontawesome-free-regular": "^5.0.7",
|
||||
"@fortawesome/fontawesome-free-solid": "^5.0.7",
|
||||
"@fortawesome/vue-fontawesome": "^0.0.22",
|
||||
"bulma": "^0.6.2",
|
||||
"mdi-vue": "^0.2.11",
|
||||
"node-sass": "^4.7.2",
|
||||
"sass-loader": "^6.0.6",
|
||||
"vue": "^2.5.2",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuex": "^3.0.1",
|
||||
"vuex-persistedstate": "^2.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.2",
|
||||
"babel-core": "^6.22.1",
|
||||
"babel-eslint": "^8.2.1",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-plugin-transform-runtime": "^6.22.0",
|
||||
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
||||
"babel-preset-env": "^1.3.2",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"chalk": "^2.0.1",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "^0.28.0",
|
||||
"eslint": "^4.15.0",
|
||||
"eslint-config-standard": "^10.2.1",
|
||||
"eslint-friendly-formatter": "^3.0.0",
|
||||
"eslint-loader": "^1.7.1",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-node": "^5.2.0",
|
||||
"eslint-plugin-promise": "^3.4.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"eslint-plugin-vue": "^4.0.0",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^1.1.4",
|
||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"node-notifier": "^5.1.2",
|
||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||
"ora": "^1.2.0",
|
||||
"portfinder": "^1.0.13",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.8",
|
||||
"postcss-url": "^7.2.1",
|
||||
"rimraf": "^2.6.0",
|
||||
"semver": "^5.3.0",
|
||||
"shelljs": "^0.7.6",
|
||||
"uglifyjs-webpack-plugin": "^1.1.1",
|
||||
"url-loader": "^0.5.8",
|
||||
"vue-loader": "^13.3.0",
|
||||
"vue-style-loader": "^3.0.1",
|
||||
"vue-template-compiler": "^2.5.2",
|
||||
"webpack": "^3.6.0",
|
||||
"webpack-bundle-analyzer": "^2.9.0",
|
||||
"webpack-dev-server": "^2.9.1",
|
||||
"webpack-merge": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
||||
22
src/App.vue
Normal file
22
src/App.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<header-bar/>
|
||||
<router-view/>
|
||||
<app-footer/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HeaderBar from '@/components/HeaderBar'
|
||||
import AppFooter from '@/components/AppFooter'
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
HeaderBar,
|
||||
AppFooter
|
||||
},
|
||||
created () {
|
||||
this.$store.commit('initState')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
214
src/assets/game_data/bundles.json
Normal file
214
src/assets/game_data/bundles.json
Normal file
@ -0,0 +1,214 @@
|
||||
{
|
||||
"bundles": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Spring Foraging Bundle",
|
||||
"room": 0,
|
||||
"reward": "Spring Seeds (30)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Summer Foraging Bundle",
|
||||
"room": 0,
|
||||
"reward": "Summer Seeds (30)",
|
||||
"items_required": 3
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Fall Foraging Bundle",
|
||||
"room": 0,
|
||||
"reward": "Fall Seeds (30)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Winter Foraging Bundle",
|
||||
"room": 0,
|
||||
"reward": "Winter Seeds (30)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Construction Bundle",
|
||||
"room": 0,
|
||||
"reward": "Charcoal Kiln",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Exotic Foraging Bundle",
|
||||
"room": 0,
|
||||
"reward": "Autumn's Bounty (5)",
|
||||
"items_required": 5
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Spring Crops Bundle",
|
||||
"room": 1,
|
||||
"reward": "Speed-Gro (20)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Summer Crops Bundle",
|
||||
"room": 1,
|
||||
"reward": "Quality Sprinkler",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Fall Crops Bundle",
|
||||
"room": 1,
|
||||
"reward": "Bee House",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Quality Crops Bundle",
|
||||
"room": 1,
|
||||
"reward": "Preserves Jar",
|
||||
"items_required": 3
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Animal Bundle",
|
||||
"room": 1,
|
||||
"reward": "Cheese Press",
|
||||
"items_required": 5
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Artisan Bundle",
|
||||
"room": 1,
|
||||
"reward": "Keg",
|
||||
"items_required": 6
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "River Fish Bundle",
|
||||
"room": 2,
|
||||
"reward": "Bait (30)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"name": "Lake Fish Bundle",
|
||||
"room": 2,
|
||||
"reward": "Dressed Spinner",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"name": "Ocean Fish Bundle",
|
||||
"room": 2,
|
||||
"reward": "Warp Totem Beach (5)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Night Fishing Bundle",
|
||||
"room": 2,
|
||||
"reward": "Small Glow Ring",
|
||||
"items_required": 3
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"name": "Crab Pot Bundle",
|
||||
"room": 2,
|
||||
"reward": "Crab Pot (3)",
|
||||
"items_required": 5
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Specialty Fish Bundle",
|
||||
"room": 2,
|
||||
"reward": "Dish O' The Sea (5)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"name": "Blacksmith's Bundle",
|
||||
"room": 3,
|
||||
"reward": "Furnace",
|
||||
"items_required": 3
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"name": "Geologists's Bundle",
|
||||
"room": 3,
|
||||
"reward": "Omni Geode (5)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Adventurer's Bundle",
|
||||
"room": 3,
|
||||
"reward": "Small Magnet Ring",
|
||||
"items_required": 2
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Chef's Bundle",
|
||||
"room": 4,
|
||||
"reward": "Pink Cake (x3)",
|
||||
"items_required": 6
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"name": "Dye Bundle",
|
||||
"room": 4,
|
||||
"reward": "Seed Maker",
|
||||
"items_required": 6
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"name": "Field Research Bundle",
|
||||
"room": 4,
|
||||
"reward": "Recycling Machine",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"name": "Fodder Bundle",
|
||||
"room": 4,
|
||||
"reward": "Heater",
|
||||
"items_required": 3
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "Enchanter's Bundle",
|
||||
"room": 4,
|
||||
"reward": "Gold Bar (5)",
|
||||
"items_required": 4
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"name": "2,500 Bundle",
|
||||
"room": 5,
|
||||
"reward": "Chocolate Cake (3)",
|
||||
"items_required": 1
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"name": "5,000 Bundle",
|
||||
"room": 5,
|
||||
"reward": "Quality Fertilizer (30)",
|
||||
"items_required": 1
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"name": "10,000 Bundle",
|
||||
"room": 5,
|
||||
"reward": "Lightning Rod",
|
||||
"items_required": 1
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"name": "25,000 Bundle",
|
||||
"room": 5,
|
||||
"reward": "Crystalarium",
|
||||
"items_required": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
57
src/assets/game_data/changelog.json
Normal file
57
src/assets/game_data/changelog.json
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"id": "Version 1.4",
|
||||
"date": "2016-04-16",
|
||||
"link": "Version-1.4",
|
||||
"changes": [
|
||||
"Fixed a bug where items skills were always being hidden",
|
||||
"Updated Season and Skill tabs to sort alphabetically",
|
||||
"Updated to Bulma 0.0.20",
|
||||
"Added a text decoration to completed bundles",
|
||||
"Fixed a bug with side-panel styling",
|
||||
"Reduced the margin size of the room names so they all fit properly in their container.",
|
||||
"Updated the bundles nav to be included in 'Hide Completed'",
|
||||
"Hide Completed and Hide Spoilers settings are now saved.",
|
||||
"Added a more thorough readme."
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Version 1.3",
|
||||
"date": "2016-04-15",
|
||||
"link": "Version-1.3",
|
||||
"changes": [
|
||||
"Bundles rewards are now hidden with other spoilers.",
|
||||
"Added a settings page to allow the user to define what information constitutes spoilers.",
|
||||
"Small Layout Changes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Version 1.2",
|
||||
"date": "2016-04-14",
|
||||
"link": "Version-1.2",
|
||||
"changes": [
|
||||
"Added an 'All Season' nav item in the Seasons tab. This shows items that are available in all seasons. Other season tabs now show items that are available in that season and at most 2 others. (#39)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Version 1.1",
|
||||
"date": "2016-04-14",
|
||||
"link": "Version-1.1",
|
||||
"changes": [
|
||||
"Added bundle completion numbers (#40)",
|
||||
"'Hide Completed' toggle now hides items in completed bundles, even if the item is not checked. (#44)",
|
||||
"Buttons for items in bundles that have been completed, but are not checked are now transparent. (#46)",
|
||||
"Updated scripts to load via HTTPS so that users loading Github via HTTPS can use the page (#47)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Version 1.0",
|
||||
"date": "2016-04-13",
|
||||
"link": "Version-1.0",
|
||||
"changes": [
|
||||
"Initial Version"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
2497
src/assets/game_data/items.json
Normal file
2497
src/assets/game_data/items.json
Normal file
File diff suppressed because it is too large
Load Diff
34
src/assets/game_data/rooms.json
Normal file
34
src/assets/game_data/rooms.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"rooms": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Crafts Room",
|
||||
"reward": "Bridge Repair"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Pantry",
|
||||
"reward": "Greenhouse"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Fish Tank",
|
||||
"reward": "Glittering Boulder Removed"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Boiler Room",
|
||||
"reward": "Minecarts Repaired"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Bulletin Board",
|
||||
"reward": "Friendship"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Vault",
|
||||
"reward": "Bus Repair"
|
||||
}
|
||||
]
|
||||
}
|
||||
24
src/assets/game_data/seasons.json
Normal file
24
src/assets/game_data/seasons.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"seasons": [
|
||||
{
|
||||
"id": "spring",
|
||||
"order": 0,
|
||||
"name": "Spring"
|
||||
},
|
||||
{
|
||||
"id": "summer",
|
||||
"order": 1,
|
||||
"name": "Summer"
|
||||
},
|
||||
{
|
||||
"id": "fall",
|
||||
"order": 2,
|
||||
"name": "Fall"
|
||||
},
|
||||
{
|
||||
"id": "winter",
|
||||
"order": 3,
|
||||
"name": "Winter"
|
||||
}
|
||||
]
|
||||
}
|
||||
29
src/assets/game_data/skills.json
Normal file
29
src/assets/game_data/skills.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"skills": [
|
||||
{
|
||||
"id": "farming",
|
||||
"order": 0,
|
||||
"name": "Farming"
|
||||
},
|
||||
{
|
||||
"id": "mining",
|
||||
"order": 1,
|
||||
"name": "Mining"
|
||||
},
|
||||
{
|
||||
"id": "foraging",
|
||||
"order": 2,
|
||||
"name": "Foraging"
|
||||
},
|
||||
{
|
||||
"id": "fishing",
|
||||
"order": 3,
|
||||
"name": "Fishing"
|
||||
},
|
||||
{
|
||||
"id": "combat",
|
||||
"order": 4,
|
||||
"name": "Combat"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
1
src/assets/sass/main.scss
Normal file
1
src/assets/sass/main.scss
Normal file
@ -0,0 +1 @@
|
||||
@import '~bulma/bulma';
|
||||
56
src/components/AppFooter.vue
Normal file
56
src/components/AppFooter.vue
Normal file
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
<strong>Stardew Community Checklist</strong> by <a href="http://johncleaver.com">John Cleaver</a>. The source code is licensed
|
||||
<a href="http://opensource.org/licenses/mit-license.php">MIT</a>.
|
||||
</p>
|
||||
<p>
|
||||
<router-link to="/changelog">Changelog</router-link>
|
||||
</p>
|
||||
<p>
|
||||
Bundle and Item information is from the <a href="http://stardewvalleywiki.com/Stardew_Valley_Wiki">Stardew Valley Wiki</a>
|
||||
and is used under the <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0 License</a>.
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://stardewvalley.net/">Stardew Valley</a> © <a href="https://chucklefish.org/">Chucklefish LTD</a>.
|
||||
Developed by <a href="https://twitter.com/ConcernedApe">ConcernedApe</a>.
|
||||
</p>
|
||||
<p>
|
||||
<a :href="gh_address"><font-awesome-icon :icon="gh_icon"/></a>
|
||||
<a :href="reddit_address"><font-awesome-icon :icon="reddit_icon"/></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FontAwesomeIcon from '@fortawesome/vue-fontawesome'
|
||||
import faGithub from '@fortawesome/fontawesome-free-brands/faGithub'
|
||||
import faReddit from '@fortawesome/fontawesome-free-brands/faReddit'
|
||||
export default {
|
||||
name: 'app-footer',
|
||||
components: {
|
||||
'font-awesome-icon': FontAwesomeIcon
|
||||
},
|
||||
computed: {
|
||||
gh_icon () {
|
||||
return faGithub
|
||||
},
|
||||
reddit_icon () {
|
||||
return faReddit
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
gh_address: 'https://github.com/kihashi/stardew_community_checklist',
|
||||
reddit_address: 'https://www.reddit.com/r/StardewValley/comments/4ell1b/stardew_community_checklist_a_site_to_keep_track/'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
66
src/components/ButtonCheckbox.vue
Normal file
66
src/components/ButtonCheckbox.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<button class="button is-rounded"
|
||||
:class="shouldBeChecked ? checked_class : unchecked_class"
|
||||
v-on:click="updateInput"
|
||||
>
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'button-checkbox',
|
||||
model: {
|
||||
prop: 'checked',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
checked_class: {
|
||||
default: 'is-info'
|
||||
},
|
||||
unchecked_class: {
|
||||
default: ''
|
||||
},
|
||||
checked: {
|
||||
default: false
|
||||
},
|
||||
value: String,
|
||||
trueValue: {
|
||||
default: true
|
||||
},
|
||||
falseValue: {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
shouldBeChecked () {
|
||||
if (this.checked instanceof Array) {
|
||||
return this.checked.includes(this.value)
|
||||
}
|
||||
|
||||
return this.checked === this.trueValue
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateInput () {
|
||||
if (this.checked instanceof Array) {
|
||||
let newValue = [...this.checked]
|
||||
|
||||
if (!this.shouldBeChecked) {
|
||||
newValue.push(this.value)
|
||||
} else {
|
||||
newValue.splice(newValue.indexOf(this.value), 1)
|
||||
}
|
||||
|
||||
this.$emit('change', newValue)
|
||||
} else {
|
||||
this.$emit('change', this.shouldBeChecked ? this.falseValue : this.trueValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
54
src/components/HeaderBar.vue
Normal file
54
src/components/HeaderBar.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<section class="hero is-info is-bold">
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<h1 class="is-size-3 has-text-weight-semibold is-hidden-mobile">Stardew Community Checklist</h1>
|
||||
<h1 class="is-size-3 has-text-weight-semibold is-hidden-tablet">SCC</h1>
|
||||
</a>
|
||||
<div class="navbar-burger"
|
||||
v-bind:class="{ 'is-active': menu_active }"
|
||||
@click="menu_active = !menu_active"
|
||||
>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-menu"
|
||||
v-bind:class="{ 'is-active': menu_active }">
|
||||
<div class="navbar-end">
|
||||
<router-link v-for="route in named_routes"
|
||||
:key="route.order"
|
||||
class="navbar-item"
|
||||
@click.native="menu_active = false"
|
||||
:to="route">
|
||||
{{route.name}}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'header-bar',
|
||||
data: function () {
|
||||
return {
|
||||
menu_active: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
named_routes: function () {
|
||||
return this.$router.options.routes.filter(route => route.hasOwnProperty('name'))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
40
src/components/SeasonIcon.vue
Normal file
40
src/components/SeasonIcon.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<span class="icon">
|
||||
<spring-icon v-if="season.id === 'spring'"/>
|
||||
<summer-icon v-if="season.id === 'summer'"/>
|
||||
<fall-icon v-if="season.id === 'fall'"/>
|
||||
<winter-icon v-if="season.id === 'winter'"/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SpringIcon from 'mdi-vue/FlowerIcon'
|
||||
import SummerIcon from 'mdi-vue/WhiteBalanceSunnyIcon'
|
||||
import FallIcon from 'mdi-vue/LeafIcon'
|
||||
import WinterIcon from 'mdi-vue/SnowflakeIcon'
|
||||
export default {
|
||||
name: 'season-icon',
|
||||
props: {
|
||||
season: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: function () {
|
||||
return {
|
||||
id: 'spring',
|
||||
name: 'Spring'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SpringIcon,
|
||||
SummerIcon,
|
||||
FallIcon,
|
||||
WinterIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
43
src/components/SkillIcon.vue
Normal file
43
src/components/SkillIcon.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<span class="icon">
|
||||
<farming-icon v-if="skill.id === 'farming'"/>
|
||||
<mining-icon v-if="skill.id === 'mining'"/>
|
||||
<foraging-icon v-if="skill.id === 'foraging'"/>
|
||||
<fishing-icon v-if="skill.id === 'fishing'"/>
|
||||
<combat-icon v-if="skill.id === 'combat'"/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FarmingIcon from 'mdi-vue/CowIcon'
|
||||
import MiningIcon from 'mdi-vue/DiamondIcon'
|
||||
import ForagingIcon from 'mdi-vue/MushroomIcon'
|
||||
import FishingIcon from 'mdi-vue/FishIcon'
|
||||
import CombatIcon from 'mdi-vue/SwordIcon'
|
||||
export default {
|
||||
name: 'skill-icon',
|
||||
props: {
|
||||
skill: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: function () {
|
||||
return {
|
||||
id: 'farming',
|
||||
name: 'Farming'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FarmingIcon,
|
||||
MiningIcon,
|
||||
ForagingIcon,
|
||||
FishingIcon,
|
||||
CombatIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
23
src/components/Welcome.vue
Normal file
23
src/components/Welcome.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<section class="hero is-medium is-bold">
|
||||
<div class="hero-body">
|
||||
<h1 class="title">
|
||||
Stardew Community Checklist
|
||||
</h1>
|
||||
<h2 class="subtitle">
|
||||
Track Your Progress on the Community Center!
|
||||
</h2>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ItemCard from '@/components/item_card/ItemCard'
|
||||
export default {
|
||||
components: {ItemCard},
|
||||
name: 'welcome'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
50
src/components/bundles/BundleItems.vue
Normal file
50
src/components/bundles/BundleItems.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div id="bundle-items">
|
||||
<section class="container">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h3 class="title">
|
||||
{{bundle.name}}
|
||||
<span class="is-pulled-right">{{bundle.items_required}}</span>
|
||||
</h3>
|
||||
<h5 class="subtitle bundle-reward">
|
||||
{{bundle.reward}}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3 class="title">
|
||||
{{bundle.room.name}}
|
||||
<span class="is-pulled-right">{{bundle.room.items_required}}</span>
|
||||
</h3>
|
||||
<h5 class="subtitle">
|
||||
{{bundle.room.reward}}
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Room Progress -->
|
||||
<!-- Bundle Progress -->
|
||||
<!-- </section>
|
||||
<section class="section"> -->
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-3 is-flex" v-for="bundleitem in bundle.items" :key="bundleitem.id">
|
||||
<item-card :item="bundleitem.item"></item-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ItemCard from '@/components/item_card/ItemCard'
|
||||
export default {
|
||||
name: 'bundle-items',
|
||||
computed: {
|
||||
bundle: function () {
|
||||
return this.$store.getters.GetBundleById(this.$route.params.id)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ItemCard
|
||||
}
|
||||
}
|
||||
</script>
|
||||
52
src/components/bundles/BundleNav.vue
Normal file
52
src/components/bundles/BundleNav.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<section class="container">
|
||||
<nav class="navbar">
|
||||
<div class="navbar-brand">
|
||||
<div class="navbar-burger burger"
|
||||
v-bind:class="{ 'is-active': menu_active }"
|
||||
@click="menu_active = !menu_active"
|
||||
>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu" v-bind:class="{ 'is-active': menu_active }">
|
||||
<div class="navbar-start">
|
||||
<div class="navbar-item has-dropdown is-hoverable" v-for="room in rooms" :key="room.id">
|
||||
<a class="navbar-link">
|
||||
{{room.name}}
|
||||
</a>
|
||||
<div class="navbar-dropdown">
|
||||
<router-link
|
||||
class="navbar-item"
|
||||
v-for="bundle in room.bundles"
|
||||
:key="bundle.id"
|
||||
@click.native="menu_active = false"
|
||||
:to="{ name: 'bundle-items', params: { id: bundle.id }}">
|
||||
{{bundle.name}}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</section>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
export default {
|
||||
name: 'bundle_nav',
|
||||
data: function () {
|
||||
return {
|
||||
menu_active: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['rooms'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
16
src/components/bundles/Bundles.vue
Normal file
16
src/components/bundles/Bundles.vue
Normal file
@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
<BundleNav />
|
||||
<section class="section">
|
||||
<router-view></router-view>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BundleNav from '@/components/bundles/BundleNav.vue'
|
||||
export default {
|
||||
components: {BundleNav},
|
||||
name: 'bundles'
|
||||
}
|
||||
</script>
|
||||
30
src/components/changelog/ChangeLog.vue
Normal file
30
src/components/changelog/ChangeLog.vue
Normal file
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<section class="section">
|
||||
<div class="container is-fluid">
|
||||
<h1 class="title">
|
||||
Changelog
|
||||
</h1>
|
||||
<version v-for="version in changelog.versions" :key="version.date" :version="version"/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ChangeLogJson from '@/assets/game_data/changelog.json'
|
||||
import Version from '@/components/changelog/Version.vue'
|
||||
export default {
|
||||
name: 'changelog',
|
||||
components: {
|
||||
Version
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
changelog: ChangeLogJson
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
66
src/components/changelog/Version.vue
Normal file
66
src/components/changelog/Version.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
{{version.id}}
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<ul>
|
||||
<li v-for="change in version.changes" :key="change.date">
|
||||
{{change}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<p class="card-footer-item has-text-centered-mobile">
|
||||
Release Date: {{version.date}}
|
||||
</p>
|
||||
<p class="card-footer-item">
|
||||
<a :href="release_url" class="button">
|
||||
<span class="icon">
|
||||
<github-box/>
|
||||
</span>
|
||||
<span>Release</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GithubBox from 'mdi-vue/GithubBoxIcon'
|
||||
export default {
|
||||
name: 'version',
|
||||
components: {
|
||||
GithubBox
|
||||
},
|
||||
props: {
|
||||
version: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
id: 'Version 1.0',
|
||||
date: '2016-04-13',
|
||||
link: 'Version-1.0',
|
||||
changes: [
|
||||
'Initial Version'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
release_url () {
|
||||
return 'https://github.com/kihashi/stardew_community_checklist/releases/tag/' + this.version.link
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
67
src/components/item_card/BundleButton.vue
Normal file
67
src/components/item_card/BundleButton.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<a class="button is-rounded is-fullwidth" :class="ItemInBundle ? 'is-success' : 'is-danger'"
|
||||
@click="ToggleItemInBundle">
|
||||
<span class="icon">
|
||||
<font-awesome-icon :icon="ItemInBundle ? InBundleIcon : NotInBundleIcon"/>
|
||||
</span>
|
||||
<span class="is-size-7-mobile">{{bundleItem.bundle.name}}{{numberInBundle}}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="control">
|
||||
<router-link class="button is-rounded is-light" :to="{ name: 'bundle-items', params: { id: bundleItem.bundle.id } }">
|
||||
<span class="icon">
|
||||
<external-link/>
|
||||
</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FontAwesomeIcon from '@fortawesome/vue-fontawesome'
|
||||
import faCheckSquare from '@fortawesome/fontawesome-free-regular/faCheckSquare'
|
||||
import faSquare from '@fortawesome/fontawesome-free-regular/faSquare'
|
||||
import ExternalLink from 'mdi-vue/OpenInNewIcon'
|
||||
export default {
|
||||
name: 'bundle-button',
|
||||
components: {
|
||||
'font-awesome-icon': FontAwesomeIcon,
|
||||
ExternalLink
|
||||
},
|
||||
props: {
|
||||
bundleItem: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ItemInBundle: function () {
|
||||
return this.$store.getters.IsBundleItemRedeemed(this.bundleItem)
|
||||
},
|
||||
InBundleIcon () {
|
||||
return faCheckSquare
|
||||
},
|
||||
NotInBundleIcon () {
|
||||
return faSquare
|
||||
},
|
||||
numberInBundle () {
|
||||
return this.bundleItem.count > 1 ? ` (${this.bundleItem.count})` : ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
ToggleItemInBundle () {
|
||||
if (!this.ItemInBundle) {
|
||||
this.$store.commit('RedeemItem', this.bundleItem)
|
||||
} else {
|
||||
this.$store.commit('UndoRedeemItem', this.bundleItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
117
src/components/item_card/ItemCard.vue
Normal file
117
src/components/item_card/ItemCard.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
{{item.name}}
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content item-source">
|
||||
{{item.source}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<bundle-button v-for="bundleItem in item.bundles" :key="bundleItem.id" :bundle-item="bundleItem" :item="item"/>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer">
|
||||
<div class="card-footer-item item-seasons">
|
||||
<season-list :seasons="item.seasons"/>
|
||||
</div>
|
||||
<div class="card-footer-item item-skills">
|
||||
<skill-list :skills="item.skills"/>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SeasonList from './SeasonList'
|
||||
import SkillList from './SkillList'
|
||||
import BundleButton from './BundleButton'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BundleButton,
|
||||
SkillList,
|
||||
SeasonList
|
||||
},
|
||||
name: 'item-card',
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {
|
||||
id: 22,
|
||||
name: 'Purple Mushroom',
|
||||
source: 'Can be found in the mines or in the farm cave if you selected the mushroom perk.',
|
||||
seasons: [
|
||||
{
|
||||
id: 'spring',
|
||||
order: 0,
|
||||
name: 'Spring'
|
||||
},
|
||||
{
|
||||
id: 'summer',
|
||||
order: 1,
|
||||
name: 'Summer'
|
||||
},
|
||||
{
|
||||
id: 'fall',
|
||||
order: 2,
|
||||
name: 'Fall'
|
||||
},
|
||||
{
|
||||
id: 'winter',
|
||||
order: 3,
|
||||
name: 'Winter'
|
||||
}
|
||||
],
|
||||
skills: [
|
||||
{
|
||||
id: 'mining',
|
||||
order: 1,
|
||||
name: 'Mining'
|
||||
},
|
||||
{
|
||||
id: 'foraging',
|
||||
order: 2,
|
||||
name: 'Foraging'
|
||||
}
|
||||
],
|
||||
'bundles': [
|
||||
{
|
||||
'count': 1,
|
||||
'bundle': {
|
||||
id: 5,
|
||||
name: 'Exotic Foraging Bundle',
|
||||
room: 0,
|
||||
reward: 'Autumn\'s Bounty (5)'
|
||||
},
|
||||
'id': 24
|
||||
},
|
||||
{
|
||||
'count': 1,
|
||||
'bundle': {
|
||||
id: 23,
|
||||
name: 'Field Research Bundle',
|
||||
room: 4,
|
||||
reward: 'Recycling Machine'
|
||||
},
|
||||
'id': 25
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.card {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
48
src/components/item_card/SeasonList.vue
Normal file
48
src/components/item_card/SeasonList.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<span class='tags has-addons'>
|
||||
<season-tag v-for='season in seasons' :key='season.order' :season='season'/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SeasonTag from './SeasonTag'
|
||||
|
||||
export default {
|
||||
components: {SeasonTag},
|
||||
name: 'season-list',
|
||||
props: {
|
||||
seasons: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: function () {
|
||||
return [
|
||||
{
|
||||
id: 'spring',
|
||||
order: 0,
|
||||
name: 'Spring'
|
||||
},
|
||||
{
|
||||
id: 'summer',
|
||||
order: 1,
|
||||
name: 'Summer'
|
||||
},
|
||||
{
|
||||
id: 'fall',
|
||||
order: 2,
|
||||
name: 'Fall'
|
||||
},
|
||||
{
|
||||
id: 'winter',
|
||||
order: 3,
|
||||
name: 'Winter'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
31
src/components/item_card/SeasonTag.vue
Normal file
31
src/components/item_card/SeasonTag.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<span class="tag is-primary">
|
||||
<season-icon :season="season" class="is-small"></season-icon>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SeasonIcon from '@/components/SeasonIcon'
|
||||
export default {
|
||||
name: 'season-tag',
|
||||
props: {
|
||||
season: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: function () {
|
||||
return {
|
||||
id: 'spring',
|
||||
name: 'Spring'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SeasonIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
24
src/components/item_card/SkillList.vue
Normal file
24
src/components/item_card/SkillList.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<span class="tags has-addons">
|
||||
<skill-tag v-for="skill in skills" :key="skill.order" :skill="skill"/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SkillTag from './SkillTag'
|
||||
|
||||
export default {
|
||||
components: {SkillTag},
|
||||
name: 'skill-list',
|
||||
props: {
|
||||
skills: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
31
src/components/item_card/SkillTag.vue
Normal file
31
src/components/item_card/SkillTag.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<span class="tag is-info">
|
||||
<skill-icon :skill="skill" class="is-small"/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SkillIcon from '@/components/SkillIcon'
|
||||
export default {
|
||||
name: 'skill-tag',
|
||||
props: {
|
||||
skill: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: function () {
|
||||
return {
|
||||
id: 'farming',
|
||||
name: 'Farming'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SkillIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
32
src/components/search/ItemSearch.vue
Normal file
32
src/components/search/ItemSearch.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Search</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input class="input" placeholder="Item Name" v-bind:value="value" v-on:input="$emit('input', $event.target.value)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'item-search',
|
||||
props: {
|
||||
value: {
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
102
src/components/search/Search.vue
Normal file
102
src/components/search/Search.vue
Normal file
@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<section class="section">
|
||||
<search-form v-model="search"></search-form>
|
||||
<section class="container">
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-3 is-flex" v-for="item in filtered_items" :key="item.id">
|
||||
<item-card :item="item"></item-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SearchForm from '@/components/search/SearchForm'
|
||||
import ItemCard from '@/components/item_card/ItemCard'
|
||||
export default {
|
||||
name: 'search',
|
||||
components: {
|
||||
SearchForm,
|
||||
ItemCard
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
search: {
|
||||
name_filter: '',
|
||||
season_filter: {
|
||||
selected_seasons: ['spring', 'summer', 'fall', 'winter'],
|
||||
season_exclusive: false
|
||||
},
|
||||
skill_filter: {
|
||||
selected_skills: ['farming', 'foraging', 'mining', 'fishing', 'combat'],
|
||||
skill_exclusive: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filtered_items () {
|
||||
var self = this
|
||||
return self.$store.state.items
|
||||
.filter(item => item.name.toLowerCase().indexOf(self.search.name_filter.toLowerCase()) !== -1)
|
||||
.filter(item => this.FilterSeasons(item.seasons.map(ssn => ssn.id), this.search.season_filter))
|
||||
.filter(item => this.FilterSkills(item.skills.map(skl => skl.id), this.search.skill_filter))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
FilterSeasons (itemSeasons, seasonFilter) {
|
||||
if (seasonFilter.season_exclusive) {
|
||||
if (itemSeasons.length !== seasonFilter.selected_seasons.length) {
|
||||
return false
|
||||
} else {
|
||||
var a = itemSeasons
|
||||
var b = seasonFilter.selected_seasons
|
||||
a.sort()
|
||||
b.sort()
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
for (var season of seasonFilter.selected_seasons) {
|
||||
if (itemSeasons.indexOf(season) !== -1) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
FilterSkills (itemSkills, skillFilter) {
|
||||
if (skillFilter.skill_exclusive) {
|
||||
if (itemSkills.length !== skillFilter.selected_skills.length) {
|
||||
return false
|
||||
} else {
|
||||
var a = itemSkills
|
||||
var b = skillFilter.selected_skills
|
||||
a.sort()
|
||||
b.sort()
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
for (var season of skillFilter.selected_skills) {
|
||||
if (itemSkills.indexOf(season) !== -1) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
59
src/components/search/SearchForm.vue
Normal file
59
src/components/search/SearchForm.vue
Normal file
@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<item-search v-model.lazy="value.name_filter" v-on:input="$emit('input', $event.target.value)" />
|
||||
</div>
|
||||
<div class="column">
|
||||
<season-filter :value="value.season_filter" v-on:input="UpdateSeasons"/>
|
||||
</div>
|
||||
<div class="column">
|
||||
<skill-filter :value="value.skill_filter" v-on:input="UpdateSkills" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ItemSearch from '@/components/search/ItemSearch.vue'
|
||||
import SeasonFilter from '@/components/search/SeasonFilter.vue'
|
||||
import SkillFilter from '@/components/search/SkillFilter.vue'
|
||||
export default {
|
||||
name: 'search-form',
|
||||
props: {
|
||||
value: {
|
||||
default () {
|
||||
return {
|
||||
name_filter: '',
|
||||
season_filter: {
|
||||
selected_seasons: [],
|
||||
season_exclusive: false
|
||||
},
|
||||
skill_filter: {
|
||||
selected_skills: [],
|
||||
skill_exclusive: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
UpdateSeasons (val) {
|
||||
this.value.season_filter = val
|
||||
this.$emit('input', this.value)
|
||||
},
|
||||
UpdateSkills (val) {
|
||||
this.value.skill_filter = val
|
||||
this.$emit('input', this.value)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ItemSearch,
|
||||
SeasonFilter,
|
||||
SkillFilter
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
67
src/components/search/SeasonFilter.vue
Normal file
67
src/components/search/SeasonFilter.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Season</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field has-addons has-addons-centered">
|
||||
<div class="control" v-for="season in seasons" :key="season.order">
|
||||
<button-check :value="season.id" :checked="value.selected_seasons" v-on:change="UpdateSeasons">
|
||||
<span class="icon is-small">
|
||||
<season-icon :season="season"></season-icon>
|
||||
</span>
|
||||
</button-check>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control is-expanded">
|
||||
<button-check class="is-fullwidth" :checked="value.season_exclusive" v-on:change="UpdateExclusive">
|
||||
Exclusive
|
||||
</button-check>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SeasonIcon from '@/components/SeasonIcon'
|
||||
import ButtonCheck from '@/components/ButtonCheckbox'
|
||||
export default {
|
||||
name: 'season-filter',
|
||||
components: {
|
||||
SeasonIcon,
|
||||
ButtonCheck
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default () {
|
||||
return {
|
||||
selected_seasons: [],
|
||||
season_exclusive: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
seasons () {
|
||||
return this.$store.state.seasons
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
UpdateSeasons (val) {
|
||||
this.value.selected_seasons = val
|
||||
this.$emit('input', this.value)
|
||||
},
|
||||
UpdateExclusive (val) {
|
||||
this.value.season_exclusive = val
|
||||
this.$emit('input', this.value)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
67
src/components/search/SkillFilter.vue
Normal file
67
src/components/search/SkillFilter.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Skills</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field has-addons has-addons-centered">
|
||||
<div class="control" v-for="skill in skills" :key="skill.id">
|
||||
<button-check :value="skill.id" :checked="value.selected_skills" v-on:change="UpdateSkills">
|
||||
<span class="icon is-small">
|
||||
<skill-icon :skill="skill" />
|
||||
</span>
|
||||
</button-check>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control is-expanded">
|
||||
<button-check class="is-fullwidth" :checked="value.skill_exclusive" v-on:change="UpdateExclusive">
|
||||
Exclusive
|
||||
</button-check>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SkillIcon from '@/components/SkillIcon'
|
||||
import ButtonCheck from '@/components/ButtonCheckbox'
|
||||
export default {
|
||||
name: 'skill-filter',
|
||||
components: {
|
||||
SkillIcon,
|
||||
ButtonCheck
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default () {
|
||||
return {
|
||||
selected_skills: [],
|
||||
skill_exclusive: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
skills () {
|
||||
return this.$store.state.skills
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
UpdateSkills (val) {
|
||||
this.value.selected_skills = val
|
||||
this.$emit('input', this.value)
|
||||
},
|
||||
UpdateExclusive (val) {
|
||||
this.value.skill_exclusive = val
|
||||
this.$emit('input', this.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
19
src/main.js
Normal file
19
src/main.js
Normal file
@ -0,0 +1,19 @@
|
||||
// The Vue build version to load with the `import` command
|
||||
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
|
||||
require('./assets/sass/main.scss')
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
components: { App },
|
||||
template: '<App/>'
|
||||
})
|
||||
51
src/router/index.js
Normal file
51
src/router/index.js
Normal file
@ -0,0 +1,51 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import Welcome from '@/components/Welcome'
|
||||
import Bundles from '@/components/bundles/Bundles'
|
||||
import BundleItems from '@/components/bundles/BundleItems'
|
||||
import Search from '@/components/search/Search'
|
||||
import Changelog from '@/components/changelog/Changelog'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/welcome',
|
||||
name: 'Welcome',
|
||||
component: Welcome
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
redirect: {
|
||||
name: 'Welcome'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/bundles',
|
||||
name: 'Bundles',
|
||||
component: Bundles,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
name: 'bundle-items',
|
||||
component: BundleItems
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
path: '/search',
|
||||
component: Search
|
||||
},
|
||||
{
|
||||
name: 'Inventory',
|
||||
path: '/inventory'
|
||||
},
|
||||
{
|
||||
path: '/changelog',
|
||||
component: Changelog
|
||||
}
|
||||
],
|
||||
linkActiveClass: 'is-active'
|
||||
})
|
||||
101
src/store/index.js
Normal file
101
src/store/index.js
Normal file
@ -0,0 +1,101 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import createPersistedState from 'vuex-persistedstate'
|
||||
|
||||
import SkillJson from '@/assets/game_data/skills.json'
|
||||
import SeasonJson from '@/assets/game_data/seasons.json'
|
||||
import RoomJson from '@/assets/game_data/rooms.json'
|
||||
import BundleJson from '@/assets/game_data/bundles.json'
|
||||
import ItemJson from '@/assets/game_data/items.json'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
var prestate = {
|
||||
seasons: loadSeasons(),
|
||||
skills: loadSkills(),
|
||||
rooms: loadRooms()
|
||||
}
|
||||
|
||||
prestate.bundles = loadBundles(prestate.rooms)
|
||||
prestate.items = loadItems(prestate.bundles, prestate.skills, prestate.seasons)
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
StoredItems: {}
|
||||
},
|
||||
plugins: [
|
||||
createPersistedState({
|
||||
reducer: state => ({ StoredItems: state.StoredItems })
|
||||
})
|
||||
],
|
||||
getters: {
|
||||
IsBundleItemRedeemed: (state) => (BundleItem) => {
|
||||
return state.StoredItems.hasOwnProperty(BundleItem.id)
|
||||
},
|
||||
GetBundleById: (state) => (bundleId) => {
|
||||
return getById(state.bundles, bundleId)
|
||||
},
|
||||
GetItemById: (state) => (itemId) => {
|
||||
return getById(state.items, itemId)
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
RedeemItem (state, BundleItem) {
|
||||
Vue.set(state.StoredItems, BundleItem.id, 1)
|
||||
},
|
||||
UndoRedeemItem (state, BundleItem) {
|
||||
Vue.delete(state.StoredItems, BundleItem.id)
|
||||
},
|
||||
initState (state) {
|
||||
Vue.set(state, 'seasons', prestate.seasons)
|
||||
Vue.set(state, 'skills', prestate.skills)
|
||||
Vue.set(state, 'rooms', prestate.rooms)
|
||||
Vue.set(state, 'bundles', prestate.bundles)
|
||||
Vue.set(state, 'items', prestate.items)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function getById (array, id) {
|
||||
return array.find(x => x.id === id)
|
||||
}
|
||||
|
||||
function loadSeasons () {
|
||||
return SeasonJson.seasons
|
||||
}
|
||||
|
||||
function loadSkills () {
|
||||
return SkillJson.skills
|
||||
}
|
||||
|
||||
function loadRooms () {
|
||||
return RoomJson.rooms.map(room => {
|
||||
room.bundles = new Array(0)
|
||||
room.items_required = 0
|
||||
return room
|
||||
})
|
||||
}
|
||||
|
||||
function loadBundles (rooms) {
|
||||
return BundleJson.bundles.map(bundle => {
|
||||
bundle.room = getById(rooms, bundle.room)
|
||||
bundle.room.bundles.push(bundle)
|
||||
bundle.room.items_required += bundle.items_required
|
||||
bundle.items = new Array(0)
|
||||
return bundle
|
||||
})
|
||||
}
|
||||
|
||||
function loadItems (bundles, skills, seasons) {
|
||||
return ItemJson.items.map(item => {
|
||||
item.skills = item.skills.map(skill => getById(skills, skill))
|
||||
item.seasons = item.seasons.map(season => getById(seasons, season))
|
||||
item.bundles.map(bundleItem => {
|
||||
bundleItem.bundle = getById(bundles, bundleItem.bundle_id)
|
||||
bundleItem.item = item
|
||||
bundleItem.bundle.items.push(bundleItem)
|
||||
return bundleItem
|
||||
})
|
||||
return item
|
||||
})
|
||||
}
|
||||
0
static/.gitkeep
Normal file
0
static/.gitkeep
Normal file
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Loading…
Reference in New Issue
Block a user