Initial import

v1 of Vue.js-based site
This commit is contained in:
Daniel J. Summers 2017-07-26 22:09:53 -05:00
parent 7c777fb27c
commit 7462c816f5
67 changed files with 13291 additions and 0 deletions

18
.babelrc Normal file
View File

@ -0,0 +1,18 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["istanbul"]
}
}
}

9
.editorconfig Normal file
View 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

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
build/*.js
config/*.js

27
.eslintrc.js Normal file
View File

@ -0,0 +1,27 @@
// http://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
},
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: 'standard',
// required to lint *.vue files
plugins: [
'html'
],
// add your custom rules here
'rules': {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
}
}

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
test/unit/coverage
test/e2e/reports
selenium-debug.log
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln

8
.postcssrc.js Normal file
View File

@ -0,0 +1,8 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}

35
build/build.js Normal file
View File

@ -0,0 +1,35 @@
require('./check-versions')()
process.env.NODE_ENV = 'production'
var ora = require('ora')
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
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'
))
})
})

48
build/check-versions.js Normal file
View File

@ -0,0 +1,48 @@
var chalk = require('chalk')
var semver = require('semver')
var packageConfig = require('../package.json')
var shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
var 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 () {
var warnings = []
for (var i = 0; i < versionRequirements.length; i++) {
var 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 (var i = 0; i < warnings.length; i++) {
var warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

9
build/dev-client.js Normal file
View File

@ -0,0 +1,9 @@
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})

92
build/dev-server.js Normal file
View File

@ -0,0 +1,92 @@
require('./check-versions')()
var config = require('../config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = process.env.NODE_ENV === 'testing'
? require('./webpack.prod.conf')
: require('./webpack.dev.conf')
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable
var app = express()
var compiler = webpack(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {},
heartbeat: 2000
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}

71
build/utils.js Normal file
View File

@ -0,0 +1,71 @@
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [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) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}

18
build/vue-loader.conf.js Normal file
View File

@ -0,0 +1,18 @@
var utils = require('./utils')
var config = require('../config')
var isProduction = process.env.NODE_ENV === 'production'
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
}),
transformToRequire: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
}
}

View File

@ -0,0 +1,75 @@
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
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: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
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]')
}
}
]
}
}

35
build/webpack.dev.conf.js Normal file
View File

@ -0,0 +1,35 @@
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})
module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
},
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new FriendlyErrorsPlugin()
]
})

124
build/webpack.prod.conf.js Normal file
View File

@ -0,0 +1,124 @@
var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
var env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: config.build.env
var webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : 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 webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: {
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: process.env.NODE_ENV === 'testing'
? 'index.html'
: 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'
}),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// 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',
chunks: ['vendor']
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
var 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) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

View File

@ -0,0 +1,31 @@
// This is the webpack config used for unit tests.
var utils = require('./utils')
var webpack = require('webpack')
var merge = require('webpack-merge')
var baseConfig = require('./webpack.base.conf')
var webpackConfig = merge(baseConfig, {
// use inline sourcemap for karma-sourcemap-loader
module: {
rules: utils.styleLoaders()
},
devtool: '#inline-source-map',
resolveLoader: {
alias: {
// necessary to to make lang="scss" work in test when using vue-loader's ?inject option
// see discussion at https://github.com/vuejs/vue-loader/issues/724
'scss-loader': 'sass-loader'
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/test.env')
})
]
})
// no need for app entry during tests
delete webpackConfig.entry
module.exports = webpackConfig

6
config/dev.env.js Normal file
View File

@ -0,0 +1,6 @@
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

38
config/index.js Normal file
View File

@ -0,0 +1,38 @@
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
// 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
},
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}

3
config/prod.env.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
NODE_ENV: '"production"'
}

6
config/test.env.js Normal file
View File

@ -0,0 +1,6 @@
var merge = require('webpack-merge')
var devEnv = require('./dev.env')
module.exports = merge(devEnv, {
NODE_ENV: '"testing"'
})

13
index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>DJS Consulting</title>
<link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico">
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

10810
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

95
package.json Normal file
View File

@ -0,0 +1,95 @@
{
"name": "djs-consulting",
"version": "1.0.0",
"description": "DJS Consulting Main Web Site",
"author": "Daniel J. Summers <daniel@djs-consulting.com>",
"private": true,
"scripts": {
"dev": "node build/dev-server.js",
"start": "node build/dev-server.js",
"build": "node build/build.js",
"unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
"e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e",
"lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
},
"dependencies": {
"vue": "^2.3.3",
"vue-router": "^2.6.0"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^7.1.1",
"babel-loader": "^7.1.1",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^2.0.1",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"cssnano": "^3.10.0",
"eslint": "^3.19.0",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-html": "^3.0.0",
"eslint-config-standard": "^6.2.1",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"eventsource-polyfill": "^0.9.6",
"express": "^4.14.1",
"extract-text-webpack-plugin": "^2.0.0",
"file-loader": "^0.11.1",
"friendly-errors-webpack-plugin": "^1.1.3",
"html-webpack-plugin": "^2.28.0",
"http-proxy-middleware": "^0.17.3",
"webpack-bundle-analyzer": "^2.2.1",
"cross-env": "^5.0.1",
"karma": "^1.4.1",
"karma-coverage": "^1.1.1",
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.2",
"karma-phantomjs-shim": "^1.4.0",
"karma-sinon-chai": "^1.3.1",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.31",
"karma-webpack": "^2.0.2",
"lolex": "^1.5.2",
"mocha": "^3.2.0",
"chai": "^3.5.0",
"sinon": "^2.1.0",
"sinon-chai": "^2.8.0",
"inject-loader": "^3.0.0",
"babel-plugin-istanbul": "^4.1.1",
"phantomjs-prebuilt": "^2.1.14",
"chromedriver": "^2.27.2",
"cross-spawn": "^5.0.1",
"nightwatch": "^0.9.12",
"selenium-server": "^3.0.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"opn": "^5.1.0",
"optimize-css-assets-webpack-plugin": "^2.0.0",
"ora": "^1.2.0",
"rimraf": "^2.6.0",
"url-loader": "^0.5.8",
"vue-loader": "^12.1.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.3.3",
"webpack": "^2.6.1",
"webpack-dev-middleware": "^1.10.0",
"webpack-hot-middleware": "^2.18.0",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

130
src/App.vue Normal file
View File

@ -0,0 +1,130 @@
<template>
<div id="app">
<header>
<router-link to="/">
<img src="/static/djs-consulting.png" alt="DJS Consulting" title="DJS Consulting" />
</router-link>
<img src="/static/slogan.png" alt="Your Web Design, Hosting, and Application Solution Source"
title="Your web design, hosting, and application solution source!" />
<span>&nbsp;</span>
</header>
<div id="content">
<router-view></router-view>
</div>
<footer>
<span>A <strong><a href="/">DJS Consulting</a></strong> original design</span>
<span style="flex-grow:3;">&nbsp;</span>
<span>Secured by <strong><a href="//letsencrypt.org">Let's Encrypt</a></strong></span>
</footer>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
@import url('https://fonts.googleapis.com/css?family=Play:400,700|Source+Sans+Pro:400,400i,700');
body {
margin: 0px;
font-family: "Source Sans Pro", "Segoe UI", Ubuntu, Tahoma, "DejaVu Sans", "Liberation Sans", Arial, sans-serif;
background-color: #FFFAFA;
}
a {
color: navy;
text-decoration: none;
}
a:hover {
border-bottom: dotted 1px navy;
}
a img {
border:0;
}
acronym {
border-bottom:dotted 1px black;
}
h1, h2, h3, footer {
font-family: "Play", "Segoe UI", Ubuntu, "DejaVu Sans", "Liberation Sans", Arial, sans-serif;
}
h1 {
text-align: center;
margin: 21px 0;
font-size: 24pt;
}
h2 {
margin: 19px 0;
width: 80%;
border-bottom: solid 2px navy;
}
p {
margin: 16px 0;
}
#content {
margin: 0 15px;
font-size: 1.05em;
}
.hdr {
font-size: 14pt;
font-weight: bold;
}
.valid_img {
width: 88px;
height: 31px;
border: 0;
vertical-align: middle;
}
header {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 70px;
border-bottom:solid 2px #3A1D00;
background: #FFE88E;
}
header a:hover {
border-bottom:none;
}
.content-item {
padding-left: 5px;
padding-right: 5px;
font-size: 12pt;
}
article.page .metadata {
display: none;
}
.strike {
text-decoration: line-through;
}
footer {
border-top: solid 5px #3A1D00;
border-bottom: solid 1px #3A1D00;
padding: 1px 15px 3px 15px;
display: flex;
flex-direction: row;
justify-content: center;
/*text-align: right; */
font-size: 1em;
background-color: #FFE88E;
color: black;
clear: both;
}
footer a:link, footer a:visited {
color: black;
}
footer a:hover {
border-bottom: none;
color: maroon;
}
.alignleft {
float:left;
padding-right: 5px;
}
ul {
padding-left: 40px;
}
li {
list-style-type: disc;
}
</style>

588
src/components/AppData.vue Normal file
View File

@ -0,0 +1,588 @@
<script>
const CATEGORIES = [
{ id: 1, name: 'Web Sites and Applications' },
{ id: 2, name: 'WordPress' },
{ id: 3, name: 'Static Sites' },
{ id: 4, name: 'Personal' }
]
const APPS = [
{
id: 'bay-vista',
name: 'Bay Vista Baptist Church',
url: 'https://bayvista.org',
active: true,
categoryId: 3,
frontPageText: 'Biloxi, Mississippi',
frontPageOrder: 1,
indexText: 'Southern Baptist church in Biloxi, Mississippi',
paragraphs: [
`Bay Vista Baptist Church has served the spiritual needs of Mississippi&lsquo;s Gulf Coast for decades. They
emphasize serving their community as well; they were a hub for
<abbr title="Federal Emergency Management Agency">FEMA</abbr> during Hurricane Katrina relief and recovery
efforts, and they are a relay point for each year&rsquo;s
<a href="https://www.samaritanspurse.org/what-we-do/operation-christmas-child/">Operation Christmas
Child</a> campaign. As of late 2013, the authors of their current website were no longer around, and no one could
get to the site to update it. We proposed setting up a site based on WordPress, where multiple people could have
the ability to maintain the site, reducing the risk of that happening again. We also mentioned that such a site
could also serve a sermon podcast feed, increasing the reach of their ministry.`
],
activity: [
{
heading: 'What We Did (2014)',
narrative: `We manually downloaded all the publically-accessible parts of their old site, and used that content
to create a WordPress-based site, updating a few outdated items along the way. We also established a
podcast feed for their sermons. A few months after initially setting up the site, we updated the
theme to be more mobile-friendly.`
},
{
heading: 'What We Did (2016)',
narrative: `In the nearly three years since we had set up the site, we were the only ones updating it. We had
recently migrated some older blogs to use the static site generator Jekyll, were impressed with the
performance gains. We converted their site, to include writing a custom template to support the
podcast feed; it is now generated along with the rest of the site.`
},
{
heading: 'What We Still Do',
narrative: 'DJS Consulting hosts this site; we also publish sermons to their podcast feed weekly.'
}
]
},
{
id: 'cassy-fiano',
name: 'Cassy Fiano',
url: 'http://www.cassyfiano.com',
active: false,
categoryId: 2,
indexText: 'A &ldquo;rising star&rdquo; conservative blogger',
paragraphs: [
`Cassy Fiano (now Cassy Chesser) began blogging back in 2007 on Blogger. She worked hard to network with other
bloggers, and wrote prolifically. As she approached the end of her first year of blogging, she was about to
outgrow Blogger. She asked in a blog post if anyone had experience with Movable Type, the platform used by another
blog to which she contributed. I replied that I did not, but that I had experience with WordPress.`
],
activity: [
{
heading: 'What We Did (2008)',
narrative: `We assisted her with finding a theme, and customized that theme to contain the same sidebar elements
as her current Blogger theme. We modified her old Blogger template to send people to her new blog
(using redirection) after displaying a note that the blog had moved.`
},
{
heading: 'What We Did (2012)',
narrative: `In July 2012, we began hosting the site, as well as continuing support for theme updates. This
joined her military wife blog
<a href="/applications/hard-corps-wife" title="Hard Corps Wife &bull; DJS Consulting">Hard Corps
Wife</a>, which we had begun hosting in mid-2011.`
},
{
heading: 'What We Still Do',
narrative: `Cassy formally decommissioned this site in early 2014.`
}
]
},
{
id: 'daniel-j-summers',
name: 'Daniel J. Summers',
url: 'https://daniel.summershome.org',
active: true,
categoryId: 4,
noAboutLink: true,
frontPageText: 'Daniel&rsquo;s personal blog',
frontPageOrder: 1
},
{
id: 'daniels-weekly-devotions',
name: 'Daniel\'s Weekly Devotions',
url: 'https://devotions.summershome.org',
active: true,
categoryId: 4,
noAboutLink: true,
frontPageText: 'A word from the Word each week',
frontPageOrder: 2
},
{
id: 'dr-melissa-clouthier',
name: 'Dr. Melissa Clouthier',
url: 'http://melissablogs.com',
active: true,
categoryId: 2,
frontPageText: 'Information Pollination',
frontPageOrder: 1,
indexText: 'Politics, health, podcasts and more',
paragraphs: [
`Dr. Melissa Clouthier saw our work with
<a href="/applications/cassy-fiano" title="Cassy Fiano &bull; DJS Consulting">Cassy</a>&rsquo;s site, and asked
us to help her move off Blogger as well. Melissa blogs from the political right, but also covers health issues and
social media. She had been blogging for a several years, and wanted to bring her old content with her to her new
site.`
],
activity: [
{
heading: 'What We Did',
narrative: `We created a custom theme based on another site, and developed graphics to complement that theme. We
also imported the content from her Blogger site into the WordPress site, and created a featured
content template for the front page.`
},
{
heading: 'What We Still Do',
narrative: 'DJS Consulting continues to provide WordPress upgrades, backups, and theme tweaks.'
}
],
footnotes: [
`<em>(NOTE: The thumbnail of the site represents a new skin on the original theme; while the theme is the same,
DJS Consulting did not create the graphics.)</em>`
]
},
{
id: 'emerald-mountain-christian-school',
name: 'Emerald Mountain Christian School',
url: 'http://www.emeraldmountainchristianschool.org',
active: false,
linkInactive: true,
categoryId: 1,
indexText: 'Classical, Christ-centered education near Wetumpka, Alabama',
paragraphs: [
`Emerald Mountain Christian School is a private Christian school founded over 50 years ago. They use the Principle
Approach&reg;, which emphasizes research, reasoning, relating, and recording to help students synthesize the
information they learn, rather than just requiring rote memorization. More information about the school&rsquo;s
rich history can be found on their site.`
],
activity: [
{
heading: 'What We Did (2004)',
narrative: `They had a website with very basic information and very little styling. We developed a theme (the
one in the thumbnail), based in large part on the design of their printed materials, and they
approved the design. Initially, the site only contained the content from their previous site. We then
put their school calendar of events up on the site, where parents could find the dates for upcoming
events. Finally, we put all the material from their Parent Information Packet online, which helped
prospective families learn more about the school before visiting it.`
},
{
heading: 'What We Did (2011)',
narrative: `The underlying engine of the basic website was switched from PHP to an ASP MVC web application, and
the back-end database was switched from MySQL to a PostgreSQL database.`
},
{
heading: 'What We Did (2013)',
narrative: `We passed off the content and hosting of the site to a new maintainer. They have since redesigned
it; it is accessible via the URL above, and at
<a href="http://emcspatriots.org" title="EMCS Patriots">EMCSpatriots.org</a>.`
}
]
},
{
id: 'futility-closet',
name: 'Futility Closet',
url: 'https://futilitycloset.com',
active: true,
categoryId: 2,
frontPageText: 'An idler&rsquo;s miscellany of compendious amusements',
frontPageOrder: 2,
indexText: 'An idler&rsquo;s miscellany of compendious amusements',
paragraphs: [
`Futility Closet exists as a place to give people a break from the dullness of work, by providing puzzles,
anecdotes, and more. It began on a shared host, but was growing too large and popular for that platform.`
],
activity: [
{
heading: 'What We Did',
narrative: `We determined what the traffic requirements and size of the blog were, then made some
recommendations. Greg Ross, the site author, decided on one of our recommendations. He had backups of
the existing database, so we were able to set up a server and restore the data onto that new server.
We configured WordPress and locked down the server, and this blog was moved quickly.`
},
{
heading: 'What We Still Do',
narrative: `DJS Consulting still hosts Futility Closet, ensuring that the underlying server receives performance
and security upgrades, monitoring site performance, and maintaining regular backups.`
}
]
},
{
id: 'hard-corps-wife',
name: 'Hard Corps Wife',
url: 'http://www.hardcorpswife.com',
active: false,
categoryId: 2,
indexText: 'Cassy&rsquo;s life as a Marine wife',
paragraphs: [
`Capitalizing on the growth from her Cassy Fiano blog, Cassy (now Chesser) began a separate blog in which she
could chronicle her experience as a military spouse.`
],
activity: [
{
heading: 'What We Did',
narrative: `We customized the header and sidebar of the theme, and set up the hardcorpswife.com domain.`
},
{
heading: 'What We Still Do',
narrative: `In 2013, Cassy shifted priorities and closed this site down. She can still be found at other places
around the web.`
}
]
},
{
id: 'liberty-pundits',
name: 'Liberty Pundits',
url: 'http://libertypundits.net',
active: false,
categoryId: 2,
indexText: 'The home for conservatives',
paragraphs: [
`At its founding, Liberty Pundits was a joint venture by 3 established bloggers
(<a href="http://melissablogs.com" title="Dr. Melissa Clouthier">Melissa Clouthier</a>, Bill Dupray, and Clyde
Middleton) that, in their words, was aimed at becoming the new home for conservatives on the Internet. With the
three of them all being prolific bloggers in their own right, and the help of many contributors, Liberty Pundits
was a bustling hub of information.`
],
activity: [
{
heading: 'What We Did',
narrative: `Bill and Clyde had been part of Patriot Room, an already-recognized powerhouse, and their desire was
for Liberty Pundits to contain the content that they had contributed to Patriot Room. The technical
lead on that blog had moved on, so we did some divining of what was there. Once we deduced the
current setup, we obtained the data from that site, determined how it would need to be manipulated to
become part of a WordPress blog, then accomplished the data migration. Initially, this was deployed
on the same shared hosting account where LibertyPundits.com, their podcast distribution site, already
resided. The site&rsquo;s traffic quickly overwhelmed that solution. They then were moved by their
host to a <abbr title="Virtual Private Server">VPS</abbr>, which performed moderately better, but
still had quite a few issues, mostly related to the site&rsquo;s traffic volume. We recommended a new
server configuration, including migrating from a fully-featured web server to a more lightweight web
server, along with caching, and configured that server. This configuration eliminated the
bottlenecks, and enabled them to have several 100,000+ hit days with no appreciable slowdowns.`
},
{
heading: 'What We Still Do',
narrative: `DJS Consulting maintained the server, keeping it current with performance and security upgrades. We
also provided support to the primary 3 bloggers, when they had questions about WordPress or how the
site was performing. The site closed in August of 2011, as the primary authors moved on to other
endeavors.`
}
]
},
{
id: 'linux',
name: 'Linux Resources',
url: '/linux',
active: true,
categoryId: 1,
noAboutLink: true,
frontPageText: 'Handy information for Linux folks',
frontPageOrder: 2
},
{
id: 'mindy-mackenzie',
name: 'Mindy Mackenzie',
url: 'http://mindymackenzie.com',
active: true,
categoryId: 2,
frontPageText: 'WSJ-best-selling author of The Courage Solution',
frontPageOrder: 3,
indexText: '<em>Wall Street Journal</em> best-selling author and C-suite advisor',
paragraphs: [
`Mindy Mackenzie, the prior Chief Performance Officer of Beam, Inc., is known as the &ldquo;Velvet Hammer&rdquo;
for her tough-yet-caring style of leadership. Her <em>Wall Street Journal</em> best-selling book <em>The Courage
Solution: The Power of Truth-Telling with Your Boss, Peers, and Team</em> details her spin-free approach to
personal and business success.`
],
activity: [
{
heading: 'What We Did',
narrative: `We assumed maintenance of her site in 2015, several months in advance of the book launch of <em>The
Courage Solution</em>. We worked with her, and her publicists and other professionals, to ensure that
the book launch went smoothly. We customized her WordPress installation to support her Media
Appearances as a custom type, where they could be entered, tracked, and listed as of the date they
occurred. We also implemented rotating videos on the front page of the site.`
},
{
heading: 'What We Still Do',
narrative: 'We continue to provide backups, WordPress support, and content updates for Mindy&rsquo;s site.'
}
]
},
{
id: 'nsx',
name: 'Not So Extreme Makeover: Community Edition',
url: 'http://notsoextreme.org',
active: false,
archiveUrl: 'https://hosted.djs-consulting.com/archive/notsoextreme_org',
categoryId: 1,
indexText: 'Public site for the makeover; provides event-driven management of volunteers, donations, and families needing help',
paragraphs: [
`In January 2008, a few members of <a href="http://hoffmantown.org" title="Hoffmantown Church">Hoffmantown
Church</a> in Albuquerque, New Mexico had an idea. The ABC show
<em><a href="http://abc.go.com/shows/extreme-makeover-home-edition">Extreme Makeover: Home Edition</a></em> had
just done
<a href="http://abc.go.com/shows/extreme-makeover-home-edition/episode-detail/martinez-family/224884" title="Martinez Family &bull; Extreme Makeover: Home Edition">a
build for a pastor in the &ldquo;war zone&rdquo; area of town</a>, and this brought attention to Gerald Martinez
and the work he had done to help clean up this area of town. Through
<a href="http://www.loveincabq.org/" title="Love INC of South Albuquerque">Love INC of South Albuquerque</a>, they
learned that there were many other homes in that area that could use the &ldquo;Ty Pennington touch.&rdquo; While
the goal was not to knock down homes and build new ones, the goal was no less extreme. The goal of the &ldquo;Not
So Extreme Makeover: Community Edition&rdquo; was to help 50 families in 5 days during spring break week in 2008.
From an idea in January to 57 families helped by March 29th, it was an amazing whirlwind.`
],
activity: [
{
heading: 'What We Did',
narrative: `The call went out for the need for &ldquo;everything from carpenters to computer nerds,&rdquo; and
Daniel thought, &ldquo;Hey, I&rsquo;m a computer nerd!&rdquo; We obtained the domain name and stood
up the public website quickly using WordPress, which also allowed the coordinators to put content up.
We next began developing an application (NSXapp) where volunteers could sign up for &ldquo;X
Week&rdquo;, with over 80 different skill, talent, and ability categories. We then created a way to
identify families and their needs, and a place for people with donations to let us know what they
would be. From there, we created the ability to begin matching needs with goods (stuff) and abilities
(people), organizing the stuff into donated trailers and people into teams. During X Week, we
generated schedules and reports that were used to track the execution of the project.<br><br>
After we recovered, Love INC expressed an interest in a version that would allow them to handle these
same areas on an ongoing basis; this was the genesis of
<a href="/applications/tcms" title="The Clearinghouse Management System &bull; DJS Consulting">TCMS</a>.`
},
{
heading: 'What We Still Do',
narrative: `NSXapp was officially decommissioned in 2012. (It still exists in archived form, if a need arises to
use it again.) A <a href="//hosted.djs-consulting.com/archive/notsoextreme_org"> snapshot of the NSX
public site</a> remains as a record of what happened those three months in 2008.`
}
]
},
{
id: 'olivet-baptist',
name: 'Olivet Baptist Church',
url: 'https://olivet-baptist.org',
active: true,
categoryId: 3,
frontPageText: 'Gulfport, Mississippi',
frontPageOrder: 2,
indexText: 'Southern Baptist church in Gulfport, Mississippi',
paragraphs: [
`Olivet Baptist Church&rsquo;s pastor saw our work with
<a href="/applications/bay-vista" title="Bay Vista Baptist Church &bull; DJS Consulting">Bay Vista</a>, and asked
us what would be involved with setting up something similar for his church. Olivet did not currently have a
website.`
],
activity: [
{
heading: 'What We Did (2014)',
narrative: `We registered the domain name for the church, then set up a fresh WordPress install. They had
expressed a desire to do as much of the content of the site themselves, so we supported them as they
worked through its initial setup. We also, as with Bay Vista, established the framework for a sermon
podcast feed.`
},
{
heading: 'What We Did (2016)',
narrative: `As with Bay Vista&rsquo;s site, this was converted to be a statically-generated site. We also
created a mobile-friendly site layout that looked similar to the one they had been using.`
},
{
heading: 'What We Still Do',
narrative: `DJS Consulting hosts this site; we also publish sermons to their podcast feed weekly.`
}
]
},
{
id: 'photography-by-michelle',
name: 'Photography by Michelle',
url: 'https://www.summershome.org',
active: false,
linkInactive: true,
categoryId: 1,
indexText: 'Photography services in Albuquerque, New Mexico',
paragraphs: [
`Michelle Summers (yes, Daniel&rsquo;s wife) had been photographing her children for years. When her sons were on
sports teams, she was disappointed with the cost of team photography, and felt that she could do a better job at a
lower cost. Thus was born Photography by Michelle. She specializes in outdoor photography of families, children,
and sports teams, as well as maternity photography and holiday cards.`
],
activity: [
{
heading: 'What We Did (2007)',
narrative: `We created the site with a few custom pages, including a gallery page that would automatically
display whatever pictures were there. We also, using WordPress and a custom image plugin, set up a
site where customers can view the proofs from their photography session.`
},
{
heading: 'What We Did (2012)',
narrative: `The custom PHP/WordPress site was replaced by a custom ASP MVC web application, which handles the
front pages and the proof set galleries. The proof display was also upgraded to allow cursor-key
navigation of proofs.`
},
{
heading: 'What We Still Do',
narrative: `As Michelle is no longer doing professional photography, the current version of this site is a
simple thank-you to her customers over the years.`
}
]
},
{
id: 'prayer-tracker',
name: 'PrayerTracker',
url: 'https://prayer.djs-consulting.com',
active: true,
categoryId: 1,
frontPageText: 'A prayer request tracking website (Free for any church or Sunday School class!)',
frontPageOrder: 1,
indexText: 'Provides an ongoing, centralized prayer list for Sunday School classes and other groups',
paragraphs: [
`Years ago, Daniel was responsible for keeping up with prayer requests for his Sunday School class. To help him
keep up with requests, automatically drop requests that were old, and track long-term requests, he wrote a custom
app made up of a few pages. Over time, he added security mechanisms and other options, arriving at the site that
exists today. It is provided free for the asking to any church, Sunday School class, or small group that desires a
tool to help them establish a continuous list of prayer requests.`
],
activity: [
{
heading: 'What We Did (2005)',
narrative: `Created the original site using PHP, storing the data in a MySQL database.`
},
{
heading: 'What We Did (2011)',
narrative: `We rewrote this application using ASP MVC 3 backed by a PostgreSQL database, building the security
additions from the ground up, and posturing it for an interface with
<a href="/applications/virtual-prayer-room" title="Virtual Prayer Room &bull; DJS Consulting">Virtual
Prayer Room</a>.`
},
{
heading: 'What We Did (2012)',
narrative: `In April 2012, version 4.0 was released with support for Spanish - our first multi-lingual
application!`
},
{
heading: 'What We Still Do',
narrative: `Host and maintain this application.`
}
]
},
{
id: 'riehl-world-news',
name: 'Riehl World News',
url: 'http://riehlworldview.com',
active: true,
categoryId: 2,
frontPageText: 'Riehl news for real people',
frontPageOrder: 4,
indexText: 'Riehl news for real people',
paragraphs: [
`Dan Riehl began blogging as &ldquo;The Carnivorous Conservative&rdquo; back in 2004, specializing in the areas of
crime and politics. He changed to &ldquo;Riehl World View&rdquo; a short time later, and writes both news and
opinion pieces. He was a prolific blogger, publishing over 15 posts a day on most days. He wanted to take his blog
in a different direction, and was having trouble getting his Movable Type blog do move with him.`
],
activity: [
{
heading: 'What We Did',
narrative: `We spoke with him regarding his ideal direction and assisted through the selection and customization
of his eventual chosen theme. We also did some work on the customization of that theme. Additionally,
we imported the large volume of posts from the Movable Type blog into his new WordPress blog.`
},
{
heading: 'What We Still Do',
narrative: `DJS Consulting continues to provide backups and WordPress updates for Riehl World News.`
}
]
},
{
id: 'tcms',
name: 'The Clearinghouse Management System',
url: 'http://tcms.us',
active: false,
categoryId: 1,
indexText: 'Assists a needs clearinghouse in connecting people with needs to people that can help meet those needs',
paragraphs: [
`The TCMS motto, &ldquo;Putting People Over Paperwork,&rdquo; sums up the mission of this system. To successfully
run a needs clearinghouse, such as those run by Love INC affiliates, there is a lot of paperwork involved. Clients
must be tracked, along with their needs; these needs must be verified; resources for goods and services must be
known; volunteers must be known and sent communications to keep them involved. All of this adds up to a
significant recordkeeping (i.e., paperwork) burden.`,
`TCMS addresses these issues by providing a repository for all clearinghouse operation needs. It can eliminate
duplication of work, as well as link clients with goods and services. It also provides the means to communicate
with volunteers, either en masse or using selective criteria. This allows the recordkeeping requirement to be
smaller and quicker, giving more time for the actual helping of clients. It uses WordPress for its front end; this
can provide organizations with a web presence that they can maintain without having to employ a web guru, using
WordPress&rsquo;s <abbr title="What You See Is What You Get">WYSIWYG</abbr> editor and management tools.`,
`TCMS was decommissioned in 2014.`
]
},
{
id: 'tech-blog',
name: 'DJS Consulting Tech Blog',
url: 'https://techblog.djs-consulting.com',
active: true,
categoryId: 3,
frontPageText: 'Technical information (AKA &ldquo;geek stuff&rdquo;) from DJS Consulting',
frontPageOrder: 3,
indexText: 'Geek stuff from DJS Consulting',
paragraphs: [
`The DJS Consulting Tech Blog grew from Daniel&rsquo;s personal experience with learning and using the Linux
operating system. His first experience with blogging consisted of pages that had to be edited every time a new
post was made. The initial posts were titled &ldquo;My Linux Adventure,&rdquo; and existed as a copy of this
home-grown blog. The DJS Consulting Tech Blog has that, plus tech tips regarding many different computer
products. It covers web servers, databases, programming languages (a lot of PHP), and open-source software. DJS
Consulting also hosts 64-bit RPM builds of xine, a Linux multimedia player; the tech blog, via the RSS feed for
that category, can deliver notices of updated versions directly to subscribed users. Finally, it also contains
notices of new versions of DJS Consulting-developed WordPress plug-ins (&ldquo;Daniel&rsquo;s Dropdowns&rdquo;
<em>(inactive, as its functionality is now part of the WordPress core)</em> and &ldquo;HCSB Verse of the Day
(Plus)&rdquo;).`,
`The original theme, &ldquo;Almost Spring,&rdquo; started as a pastel green and orange theme for WordPress.
However, it was customized to match the original look and feel of those initial static pages that served as the
blog from 2004-2006, and was converted to a BlogEngine.NET theme when we changed blogging platforms. When we went
back to WordPress, we changed to a simple theme called &ldquo;Mantra,&rdquo; which has unobtrusive social media
integration.`
]
},
{
id: 'the-shark-tank',
name: 'The Shark Tank',
url: 'http://shark-tank.net',
active: false,
categoryId: 2,
indexText: 'Floridas political feeding frenzy',
paragraphs: [
`The Shark Tank is a news and opinion site centered on south Florida politics (and the state at large). They
provided extensive coverage of Rep. Allen West&rsquo;s winning campaign in 2010, and are continuing their focused
news and opinion to current political races.`
],
activity: [
{
heading: 'What We Did',
narrative: `They were displeased with their current theme, and had found a theme (and a demo site) that they
preferred. We set up the theme, ensured that their content would fit in the new theme&rsquo;s
requirements, and helped them turn off parts that they didn&rsquo;t need. We also converted the
social media connections from their old site to a style that would work nicely in the new theme.`
}
]
},
{
id: 'virtual-prayer-room',
name: 'Virtual Prayer Room',
url: 'https://virtualprayerroom.us',
active: false,
categoryId: 1,
indexText: 'Gives prayer warriors access to requests from wherever they may be, and sends them daily updates',
paragraphs: [
`Many churches have prayer rooms - rooms set aside for people to come in to pray. Hoffmantown Church in
Albuquerque, New Mexico was one of these churches. However, they had seen the use of this physical prayer room
dwindling over the years. People had become less willing to drive to the church, especially at night, and security
became an issue as well; either prayer warriors had to know how to disable the security system, or the church
would have to remain unlocked.`,
`Having seen our work with the
<a href="/applications/nsx/" title="Not So Extreme Makeover: Community Edition &bull; DJS Consulting">Not So
Extreme Makeover: Community Edition</a>, the church contacted us to see if something similar could be developed to
help their prayer ministry. The resulting application that was developed extends the prayer room to wherever the
prayer warrior can get an Internet connection! Prayer warriors can enlist right from the site, and must be
approved. Requests and updates are tracked by date/time, and warriors can record when they&rsquo;ve prayed for a
request from the site, or from clicking a link in the daily e-mail they receive with requests from their interest
areas. As many prayer needs are confidential, security and confidentiality are very important. Virtual Prayer Room
ensures these by providing varying security levels for prayer warriors and the ability to mark each request as
confidential.`,
`In 2016, Hoffmantown Church elected to begin using another package for their prayer requests. While a few other
churches had expressed interest in it, none ultimately decided to use it; so, in 2017, Virtual Prayer Room was
officially decommissioned.`
]
}
]
export default {
categories: CATEGORIES,
apps: APPS
}
</script>

View File

@ -0,0 +1,67 @@
<template>
<article>
<page-title :title="pageTitle" />
<h1>{{ application.name }}<br>
<small><small>
<a v-if="application.active || application.linkInactive" :href="application.url">{{ application.url }}</a>
<span v-if="!application.active && !application.linkInactive">{{ application.url }}</span>
</small></small>
</h1>
<aside>
<img :src="imageLink">
</aside>
<p v-for="(p, idx) in application.paragraphs" v-bind:key="idx" v-html="p"></p>
<p v-for="(act, idx) in application.activity" v-bind:key="idx" v-bind:act="act">
<strong>{{ act.heading }}</strong> &ndash; <span v-html="act.narrative"></span>
</p>
<p v-for="(p, idx) in application.footnotes" v-bind:key="idx" v-html="p"></p>
<p>
<br>
<router-link :to="{ name: 'ApplicationList' }">&laquo; Back to Web Sites and Applications</router-link>
</p>
</article>
</template>
<script>
import AppData from './AppData.vue'
import PageTitle from './PageTitle.vue'
export default {
props: ['app'],
data: function () {
return {}
},
computed: {
application: function () {
return AppData.apps.find(app => app.id === this.$props.app)
},
imageLink: function () {
return `/static/screenshots/${this.application.id}.png`
},
pageTitle: function () {
return `${this.application.name} « Applications`
}
},
components: {
PageTitle
}
}
</script>
<style scoped>
h1 {
line-height: .75em;
}
aside {
float: right;
width: auto;
padding-left: 15px;
}
aside img {
border: solid 3px #3A1D00;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
</style>

View File

@ -0,0 +1,30 @@
<template>
<article>
<page-title title="Applications" />
<h1>Web Sites and Applications</h1>
<h2>Current Projects</h2>
<application-list-item v-for="app in current" v-bind:app="app" v-bind:key="app.id" />
<h2>Past Projects</h2>
<application-list-item v-for="app in past" v-bind:app="app" v-bind:key="app.id" />
</article>
</template>
<script>
import AppData from './AppData.vue'
import ApplicationListItem from './ApplicationListItem.vue'
import PageTitle from './PageTitle.vue'
export default {
name: 'application-list',
data: function () {
return {
current: AppData.apps.filter(app => app.active && !app.noAboutLink),
past: AppData.apps.filter(app => !app.active && !app.noAboutLink)
}
},
components: {
ApplicationListItem,
PageTitle
}
}
</script>

View File

@ -0,0 +1,28 @@
<template>
<p>
<span class="app-name" v-html="app.name"></span> &nbsp;~&nbsp;
<router-link :to="{ name: 'Application', params: { app: app.id } }">About</router-link>
<span v-if="app.active"> &nbsp;~&nbsp; <a :href="app.url">Visit</a></span>
<span v-if="!app.active && app.archiveUrl"> &nbsp;~&nbsp; <a :href="app.archiveUrl">Visit</a> <em>(archive)</em></span><br>
<span v-html="app.indexText"></span>
</p>
</template>
<script>
export default {
name: 'application-list-item',
props: ['app'],
data: function () {
return {}
}
}
</script>
<style scoped>
.app-name {
font-family: "Play", "Segoe UI", Ubuntu, "DejaVu Sans", "Liberation Sans", Arial, sans-serif;
font-size: 1.1em;
font-weight: bold;
color: maroon;
}
</style>

206
src/components/Home.vue Normal file
View File

@ -0,0 +1,206 @@
<template>
<article>
<page-title title="Welcome!" />
<h1>Welcome to DJS Consulting!</h1>
<app-sidebar />
<p>
DJS Consulting can develop an interactive web application to fit almost any need.
<router-link to="/applications" title="Web Sites and Applications">View the complete list of our current web
sites and applications!</router-link>
</p>
<h2>Process Automation and User Engagement</h2>
<p>
Computers can be used to augment or automate nearly any process; could you think of generating bank statements,
processing mailing lists, or tracking orders without some form of automation? We develop web-based solutions to
automate <em>your</em> processes, ensuring that your business constraints are satisfied; these systems can run on
the Internet or your private network. For Internet-facing solutions, we engineer solutions that allow them to
interact with you securely, presented in an engaging manner. And, by "engagement," we are not describing intrusive
page pop-ups and other <span class="strike">marketing gimmicks</span> web annoyances; we determine an optimal user
experience for <em>your</em> customers, and tailor the solution to work for both of you.
</p>
<p>Several of our projects fit this description.</p>
<ul>
<li>
<router-link to="/applications/virtual-prayer-room" title="Virtual Prayer Room">Virtual Prayer
Room</router-link> helped the prayer ministry of
<a href="http://www.hoffmantown.org" title="Hoffmantown Church in Albuquerque, NM">Hoffmantown Church</a>
enable their prayer warriors to have access to requests wherever they are, even in their inbox once a day!
</li>
<li>
<router-link to="/applications/tcms" title="TCMS">TCMS</router-link> was an application that helped
organizations such as <a href="http://www.loveincabq.org">Love INC of South Albuquerque</a> connect people with
needs to people who can help fulfill those needs. TCMS sprung from the
<a href="http://hosted.djs-consulting.com/archive/notsoextreme_org" title="Not So Extreme Makeover: Community Edition (Archive)">Not
So Extreme Makeover: Community Edition</a> in Albuquerque, New Mexico during spring break 2008; we not only
developed the public presence, but a private system called
<router-link to="/applications/nsx/" title="NSX &bull; DJS Consulting">NSXapp</router-link> that enabled the
management of the volunteers, families, and things for this massive effort.
</li>
<li>
We continue to offer
<router-link to="/applications/prayertracker" title="PrayerTracker &bull; DJS Consulting">PrayerTracker</router-link>,
a free-to-use web application that helps Sunday School classes (or other small groups) generate a prayer request
list; it provides a central place for list management and continuity.
</li>
</ul>
<h2>Information Publicizing <small><em>(including WordPress)</em></small></h2>
<p>
In the early days of the World Wide Web, it was known as the "information superhighway." From its inception, the
web's primary goal is information. The open nature of the Internet allows anyone, anywhere to say anything,
provided they can connect a machine to the network. In fact, there are software products to handle everything
except creating the content; all you have to bring is the ability to form a coherent thought, and type that
thought into a box. <a href="https://wordpress.org" title="WordPress">WordPress</a> is one of the most popular
<abbr title="Web Log">blog</abbr>ging platforms in use today; it allows authors to concentrate on the content of
their websites, rather than forcing authors to turn into programmers.
</p>
<h3>Custom-Built Sites</h3>
<ul>
<li>
We developed and maintained the site for <a href="http://www.emeraldmountainchristianschool.org">Emerald
Mountain Christian School</a> for 9 years, where they had information about the type of curriculum they teach,
the school's 40+-year history, a calendar of events, and how to get more information.
</li>
<li>
We built and maintained the site for <a href="http://www.summershome.org">Photography by Michelle</a>, which had
information, prices, and samples of the photographer's work, as well as the ability for customers to view proofs
and make photo selections online.
</li>
<li>
The sites for <a href="//bayvista.org" title="Bay Vista Baptist Church">Bay Vista Baptist Church</a> and
<a href="//olivetbaptist.org" title="Olivet Baptist Church">Olivet Baptist Church</a> utilize a "static site
generator," where the entire site is generated from source files, then served. It requires no back-end database,
which means that the server can send them as fast as its clients can take them. These two sites even have a
generated podcast feed! Adding content to these types of sites requires a bit more technical knowledge beyond
"typing text in a box," but it is a great way to build ultra-fast, scalable web sites.
</li>
<li>
This site is a single-page application (SPA) utilizing the <a href="//vuejs.org">Vue.js</a> JavaScript
framework. The application pages are generated based on an internal data set, and the other pages are simple
text components. Its bundling means that the initial page is small, and after the initial load, it runs entirely
in the browser or on a phone or tablet. Sites that reference external data sets would still need to access the
Internet to retrieve data, but this is much more efficient than having to download the entire page every single
click.
</li>
</ul>
<h3>WordPress Design, Customization, and Support</h3>
<ul>
<li>
We helped <router-link to="/applications/cassy-fiano" title="Cassy Fiano">Cassy Fiano</router-link> and
<a href="http://melissablogs.com" title="Dr. Melissa Clouthier &bull; Information Pollination">Dr.Melissa
Clouthier</a> both move their blogs from Blogspot to their own domains.
</li>
<li>
We migrated <router-link to="/applications/liberty-pundits" title="Liberty Pundits">Liberty
Pundits</router-link> from a custom blog platform to WordPress, and set up and maintained their server, which
routinely cleared 100,000 hits per day in its prime.
</li>
<li>
For <a href="//www.futilitycloset.com" title="Futility Closet">Futility Closet</a>, we moved their site from a
shared hosting platform to its own <abbr title="Virtual Private Server">VPS</abbr>, to enable it to handle its
ever-increasing traffic.
</li>
<li>
TCMS and NSXapp both used WordPress as their front end, which also provided a public web presence that the
customers could update themselves.
</li>
</ul>
<p>
On our <a href="//techblog.djs-consulting.com" title="DJS Consulting Tech Blog">tech blog</a> you can browse the
<a href="//techblog.djs-consulting.com/category/wordpress" title="WordPress - DJS Consulting Tech Blog">WordPress</a>
category for information on plug-ins, and you'll find that the themes on all of the WordPress blogs linked on the
right have been customized.
</p>
<h2>Web Services</h2>
<p>
A web service is a way of using the Internet to provide or accept information that makes sense to computers; this
allows other sites or applications to consume information from, or provide information to, your service. This
enables communication between applications, without having to establish any communication channels other than the
ones that web browsers already use. It isn't the best fit for every application, but when it is useful, it is
<em>very</em> useful.
</p>
<p>
Photography by Michelle has a web service that a desktop application utilizes to create the online proof sets
right from the computer where the images reside. We also
<a href="//techblog.djs-consulting.com/2010/4040-web-service.html" title="40/40 Web Service">wrote a service</a>
for the 2010 <a href="http://erlc.com/4040/" title="40/40 Prayer Vigil - Ethics and Religious Liberty Commission of the Southern Baptist Convention">40/40
Prayer Vigil</a>, which was utilized by several sites to display the current day's (or hour's) prayer focus, and
<a href="//techblog.djs-consulting.com/2012/4040-web-service-for-2012.html" title="40/40 Web Service for 2012">wrote
one for 2012</a> as well. <em>(As the ERLC does not host these any more, this service is no longer active.)</em>
</p>
<h2>Legacy Data Sharing</h2>
<p>
Our background in mainframe applications gives us a knowledgeable perspective on retrieving information from
older, &ldquo;legacy&rdquo; systems. This data can be migrated to a more modern relational or document database,
where a web application can retrieve the information; in some cases, the data can even be exposed as a web service
in place. These types of systems are often a great way for companies to expose their data to their customers,
without having to move their day-to-day system from its current environment. While we currently have no active
projects along these lines, our developers have done them in the past for other organizations; sadly, none can be
linked publicly.
</p>
<h2>Why Web-Based?</h2>
<p>
Developing a web-based solution has many advantages, whether that application can be used just on a local, private
network (an intranet), or on the Internet.
</p>
<ul>
<li>
The application is available from any computer connected to the network &mdash; your home computer, your mobile
phone or tablet, a shared comptuer in a library - wherever!
</li>
<li>
There is no special software to install &mdash; every computer and mobile device has a web browser on it, and we
ensure our solutions work on today's most popular web browsers, including Microsoft&reg; Edge, Mozilla Firefox,
and Google Chrome.
</li>
<li>
Web-based solutions are easy to implement in a step-by-step fashion, so your most critical needs can be
addressed and deployed first. Enhancements are generally easy to do as well.
</li>
</ul>
<p>
We'd be happy to discuss your information technology needs, and how we may be able to help you. Just
<a href="mailto:daniel@djs-consulting.com">e-mail us</a> and let us know what we can do for you!
</p>
</article>
</template>
<script>
import AppSidebar from './sidebar/AppSidebar.vue'
import PageTitle from './PageTitle.vue'
export default {
name: 'home',
data: function () {
return {
toggleExamples: function (e) {
e.preventDefault()
const el = document.getElementById('test')
if (el.style.height === '0px') {
el.style.height = 'auto'
const hite = el.clientHeight
console.log('height = ' + hite)
el.style.height = '0'
window.requestAnimationFrame(function () {
el.style.overflow = 'visible'
el.style.height = hite + 'px'
setTimeout(function () { el.style.overflow = 'visible' }, 1000)
})
} else {
el.style.height = '0'
setTimeout(function () { el.style.overflow = 'hidden' }, 1000)
}
}
}
},
components: {
AppSidebar,
PageTitle
}
}
</script>
<style>
.examples {
transition: all 1s ease;
}
</style>

View File

@ -0,0 +1,15 @@
<script>
export default {
name: 'page-title',
props: ['title'],
created () {
document.title = `${this.title} « DJS Consulting`
},
watch: {
title () {
document.title = `${this.title} « DJS Consulting`
}
},
render () { }
}
</script>

View File

@ -0,0 +1,221 @@
<template>
<article>
<page-title title="Installing WBEL4 (RHEL4) on an Averatec 6200 Laptop « Linux Resources" />
<h1>Installing WBEL4 (RHEL4) on an Averatec 6200 Laptop</h1>
<aside>
<p>
<strong>Topics:</strong><br>
<a href="#what">What Do I Have?</a><br>
<a href="#partitioning">Partitioning</a><br>
<a href="#installing">Installation</a><br>
<a href="#video">Video</a><br>
<a href="#wireless">Wireless Networking</a><br>
<a href="#tweaks">Other Tweaks</a><br>
<a href="#left">What&rsquo;s Left?</a>
</p>
</aside>
<p>
As an early Father&rsquo;s Day 2005 present, I received a new Averatec 6240 laptop. Being the Linux enthusiast
that I am, within 24 hours of getting it, I had wiped the Windows XP Home Edition&reg; that came on it. The
previous week, I had downloaded <a href="http://www.whiteboxlinux.org">White Box Enterprise Linux
(http://www.whiteboxlinux.org)</a> version 4, with an eye to upgrading my existing computer, so I had a recent set
of CDs burned already. (WBEL is a clone of Red Hat Enterprise Linux, as is CentOS, so these instructions may be
helpful for all RHEL derivatives.) I&rsquo;ve organized this into topics &ndash; just click one to jump right to
it.
</p>
<p>
<small><em>(Note: This information is provided as information only, and a reflection of what I did to get my
laptop running the way I wanted it. It may or may not work for you &ndash; no guarantee is specified or implied,
and I cannot be held responsible for any hardware failure or data loss you may encounter by following any of the
steps in this guide. At any rate, it&rsquo;s still probably worth double what you&rsquo;re paying for
it&hellip;&nbsp; ;&gt;)</em></small>
</p>
<p>
<del>
<strong>A Work in Progress</strong> &ndash; This page is not complete &ndash; check the &ldquo;What&rsquo;s
Left?&rdquo; topic to see what changes still need to be made before I&rsquo;ll consider it
&ldquo;complete&rdquo;.
</del>
This page is as complete as it&rsquo;s ever going to be.
</p>
<h2><a name="what"></a>What Do I Have?</h2>
<p>
To determine what type of hardware you have, you can use the command <tt>/sbin/lspci</tt>. On this laptop, I was
able to boot with <a href="http://wwww.knoppix.com">Knoppix</a>, one of the most feature-rich Linux Live CD
distributions out there. The list on this laptop is shown below&hellip;
</p>
<blockquote>
<pre>0000:00:00.0 Host bridge: Silicon Integrated Systems [SiS] 760/M760 Host (rev 03)
0000:00:01.0 PCI bridge: Silicon Integrated Systems [SiS] SG86C202
0000:00:02.0 ISA bridge: Silicon Integrated Systems [SiS] SiS85C503/5513 (LPC Bridge) (rev 25)
0000:00:02.5 IDE interface: Silicon Integrated Systems [SiS] 5513 [IDE]
0000:00:02.6 Modem: Silicon Integrated Systems [SiS] AC'97 Modem Controller (rev a0)
0000:00:02.7 Multimedia audio controller: Silicon Integrated Systems [SiS] Sound Controller (rev a0)
0000:00:03.0 USB Controller: Silicon Integrated Systems [SiS] USB 1.0 Controller (rev 0f)
0000:00:03.1 USB Controller: Silicon Integrated Systems [SiS] USB 1.0 Controller (rev 0f)
0000:00:03.3 USB Controller: Silicon Integrated Systems [SiS] USB 2.0 Controller
0000:00:04.0 Ethernet controller: Silicon Integrated Systems [SiS] SiS900 PCI Fast Ethernet (rev 91)
0000:00:0a.0 CardBus bridge: ENE Technology Inc CB1410 Cardbus Controller (rev 01)
0000:00:0e.0 Network controller: RaLink Ralink RT2500 802.11 Cardbus Reference Card (rev 01)
0000:00:18.0 Host bridge: Advanced Micro Devices [AMD] K8 NorthBridge
0000:00:18.1 Host bridge: Advanced Micro Devices [AMD] K8 NorthBridge
0000:00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 NorthBridge
0000:00:18.3 Host bridge: Advanced Micro Devices [AMD] K8 NorthBridge
0000:01:00.0 VGA compatible controller: Silicon Integrated Systems [SiS] 661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP</pre>
</blockquote>
<p>
This may seem like a waste of time (especially if you don&rsquo;t have a Knoppix CD lying around already, but this
information can be invaluable when you try to get these devices working. A couple of things jump out from the
above list &ndash; most of the hardware in this box was made by Silicon Integrated Systems, with the notable
exception of the cardbus controller and the 802.11 (wireless) network adapter.
</p>
<h2><a name="partitioning"></a>Partitioning</h2>
<p>
Partitioning was a particular concern for me, as I wanted to set up a dual-boot Windows/Linux installation.
Windows must have its files on the first partition for it to successfully boot, so I set up Windows first. I
messed up a bit, as I tried to declare a 100MB boot partition as the first partition. Windows insisted on
formatting it, so it could put its boot files on it, so I basically have a wasted 100MB at the front of my drive.
(Not a big deal&hellip;)
</p>
<p>
I created a 12GB partition for Windows, and a 15GB partition for &ldquo;shared&rdquo; data &ndash; I formatted it
as FAT32 (vfat), so that both Windows and Linux can read it. This was fine, but combined with my extra 100MB
partition, the WBEL installer was unable to automatically partition the remaining free space.&nbsp; This
isn&rsquo;t a big problem &ndash; there&rsquo;s are two pretty simple rules to remember about partitions that
Linux needs&hellip;
</p>
<ul>
<li>
There must be a root (&ldquo;/&rdquo;) partition (I calculated the size of this by subtracting the amount of
swap space I needed (see the next rule), then allocating the remaining free space to the root partition)
</li>
<li>
There must be a swap partition (actually the &ldquo;swap&rdquo; filesystem type) that is twice as big as your
RAM (for this machine, that meant 1024MB)
</li>
</ul>
<p>Here is my current partition table&hellip;</p>
<blockquote>
<pre># /sbin/fdisk -l
Disk /dev/hda: 60.0 GB, 60011642880 bytes
255 heads, 63 sectors/track, 7296 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 13 104391 6 FAT16
/dev/hda2 14 7295 58492665 f W95 Ext'd (LBA)
/dev/hda5 14 1580 12586896 7 HPFS/NTFS
/dev/hda6 1581 3589 16137261 b W95 FAT32
/dev/hda7 3590 7158 28667961 83 Linux
/dev/hda8 7159 7289 1052226 82 Linux swap</pre>
</blockquote>
<h2><a name="installing"></a>Installing</h2>
<p>
Installing Linux is naturally the first thing you&rsquo;ll need to do. However, the default install options did
not work for me. What did work was <tt>linux nofb xdriver=sis</tt>. This tells anaconda to not use a framebuffer
(which, as I read, is incompatible with most of the LCD flat-panels that laptops have), and to use the
&ldquo;sis&rdquo; (Silicon Integrated Systems) driver. Even with this, the installer will not detect the SiS video
card or the flat-panel display &ndash; but that&rsquo;s okay, just let it install with the VESA driver and a
generic 1024&times;768 layout. It&rsquo;ll be stretched, but definitely readable. (See the &ldquo;video&rdquo;
topic for how to fix this.) Also, if you really mess something up, you&rsquo;ll need to pass those parameters in
the rescue mode &ndash; the full command is <tt>linux rescue nofb xdriver=sis</tt>.
</p>
<p>
I picked the server install, and selected most packages &ndash; this setup allows me to run both GNOME and KDE,
and build applications for either. Be sure to install the system files, so you can compile kernel modules if you
need them (which you&rsquo;ll need to do for the xdriver and wireless driver). Do not skip the OpenOffice.org I18N
libraries &ndash; even though they&rsquo;re huge, it won&rsquo;t run without them. (I learned that the hard way.)
</p>
<h2><a name="video"></a>Video</h2>
<p>
I mentioned that during the install, the monitor would not be detected. Using the system viedo config, you can set
the LCD panel to 1280&times;800. Then, head over to <a href="http://www.winischhofer.at/linuxsisvga.shtml">Thomas
Winischhofer&rsquo;s site about the SiS video driver</a>. He is the author of the SiS driver that&rsquo;s
distributed with Linux, and his site has a lot of information about this chipset. On his site, he has built on
that base, in his own time, and created a very usable driver for the SiS chipset. There are links to download
various products &ndash; I downloaded the driver and the sisctrl program, and built them.
</p>
<p>
Once I restarted the machine, it was better, but not quite there. I posted on the forums (also on the Winischhofer
site) about my problem, and the author himself responded
(<a href="http://www.winischhofer.at/sisforum/viewtopic.php?t=76">the thread is here</a>).&nbsp; In my case,
1280&times;800 was not put in by the driver &ndash; but, I think it may have been because I hadn&rsquo;t set the
LCD panel settings when I installed the driver.
</p>
<h2><a name="wireless"></a>Wireless Networking</h2>
<p>
The RaLink wireless ethernet card has a very capable open-source driver. It can be downloaded from
<a href="http://rt2x00.serialmonkey.com/wiki/index.php/Main_Page">SerialMonkey&rsquo;s web site</a>. I downloaded
the driver, followed the instructions, and couldn&rsquo;t get it to work. It installed the adapter as ra0, but
Linux was finding it as eth1 - and I couldn&rsquo;t get eth1 to change to ra0, or ra0 to change to eth1. I finally
posted a message on the
<a href="http://sourceforge.net/forum/forum.php?thread_id=1294781&amp;forum_id=370891">driver&rsquo;s
SourceForge.net forums</a>, and the author told me that I needed to use <tt>make install-fedora</tt> instead of
just <tt>make install</tt>.
</p>
<p>
Every so often, I had problems getting the wireless card to connect with my home LAN. I changed my DHCP lease
times from two weeks to two hours, and that problem cleared up. I think, for some reason, the router was not
sensing when the wireless card would disconnect &ndash; so, when it tried to connect again, the router would just
ignore it. Windows didn&rsquo;t seem to have similar problems, but that&rsquo;s a small tweak to make that
hasn&rsquo;t affected any of the other computers on the network. I have gotten good responses from the developers
of the wireless driver, and hope to be able to help them track this down if they&rsquo;re interested. (They are
concentrating most of their new work on a new driver called &ldquo;rt2x00&Prime; that will work for all RaLink
RT2400 and RT2500 series network adapters, so this feature may be available in them. They&rsquo;ve also moved
their forums - <a href="http://rt2x00.serialmonkey.com/phpBB2/index.php">the official support forms can be found
here</a>.)
</p>
<h2><a name="tweaks"></a>Other Tweaks</h2>
<p>They&rsquo;ll be here soon!</p>
<h2><a name="left"></a>What&rsquo;s Left?</h2>
<p>Issues I&rsquo;m still working on&hellip;</p>
<ul>
<li>
<strong>PCMCIA</strong> &ndash; This is so slow initializing that rhgb (Red Hat&rsquo;s graphical booter)
actually switches back to console one. I&rsquo;m sure there&rsquo;s a way to make it not take so long, I just
need to figure out what it is.
</li>
<li>
<strong>Audio Input</strong> &ndash; I tried to use the microphone in jack, and nothing would take sound from
it.
</li>
<li>
<strong>Shared Data Between XP and WBEL</strong> &ndash; This is working differently than WBEL3 did &ndash; once
I figure it out, it&rsquo;ll be here too
</li>
</ul>
</article>
</template>
<script>
import PageTitle from '@/components/PageTitle.vue'
export default {
name: 'averatec',
data: function () {
return {}
},
components: {
PageTitle
}
}
</script>
<style scoped>
aside {
float: right;
width: auto;
border: solid 2px navy;
border-right: none;
padding: 5px;
border-radius: 10px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
margin-right: -15px;
}
aside p {
margin: 0;
padding: 0;
}
</style>

View File

@ -0,0 +1,38 @@
<template>
<article>
<page-title title="Linux Resources" />
<h1>Linux Resources</h1>
<p>We at DJS Consulting love Linux! Below are the resources we provide.</p>
<p>
&raquo; <router-link to="/linux/installing-wbel4-rhel4-on-an-averatec-6200-laptop" title="Installing WBEL4 (RHEL4) on an Averatec 6200 Laptop - DJS Consulting Linux Resources">Installing
Linux on an Averatec 6200 Laptop</router-link>
</p>
<p>
&raquo; <router-link to="/linux/xine-rpms-for-el-x86_64-architecture" title="xine RPMs for EL / x86_64 Architecture - DJS Consulting Linux Resources">xine
RPMs for the x86_64 EL Architecture</router-link>
</p>
<p>
&raquo; <a href="//hosted.djs-consulting.com/software" title="DJS Consulting Software Repository">DJS Consulting
Software Repository</a>
</p>
<p>
&raquo; <a href="//techblog.djs-consulting.com/category/linux" title="Linux - DJS Consulting Tech Blog">Linux
posts</a> on the <a href="//techblog.djs-consulting.com" title="DJS Consulting Tech Blog">DJS Consulting Tech
Blog</a>
</p>
</article>
</template>
<script>
import PageTitle from '@/components/PageTitle.vue'
export default {
name: 'linux',
data: function () {
return {}
},
components: {
PageTitle
}
}
</script>

View File

@ -0,0 +1,32 @@
<template>
<article>
<page-title title="xine RPMs « Linux Resources" />
<h1>xine RPMs for EL / x86_64 Architecture</h1>
<p>
The xine RPMs are now distributed through the <a href="//techblog.djs-consulting.com">DJS Consulting Tech
Blog</a>. Information about the RPMs can be found in the
<a href="//techblog.djs-consulting.com/2005/about-the-xine-rpms.html" title="About the xine RPMs">About the xine
RPMs</a> post there, including how you can use RSS or Atom feeds to be notified of updated builds.
</p>
<p>
You can also
<a href="//techblog.djs-consulting.com/category/hosted-64-bit-software/xine-rpms" title="xine RPMs">view the list
of available RPMs</a> or simply <a href="//hosted.djs-consulting.com/software/xine" title="xine RPMs">browse the
available xine files</a>.
</p>
</article>
</template>
<script>
import PageTitle from '@/components/PageTitle.vue'
export default {
name: 'xine-rpms',
data: function () {
return {}
},
components: {
PageTitle
}
}
</script>

View File

@ -0,0 +1,52 @@
<template>
<aside>
<sidebar-category v-for="category in cats" v-bind:category="category" v-bind:key="category.id" />
</aside>
</template>
<script>
import AppData from '../AppData.vue'
import SidebarCategory from './SidebarCategory.vue'
export default {
name: 'app-sidebar',
data: function () {
return { cats: AppData.categories }
},
components: {
SidebarCategory
}
}
</script>
<style scoped>
aside {
width: 200px;
float: right;
font-size: 1em;
text-align: center;
background-color: white;
border: solid 2px navy;
border-right: none;
border-radius: 10px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
margin-left:3px;
margin-right: -15px;
padding-left: 3px;
padding-right: 3px;
font-size: 80%;
clear: both;
}
aside a {
font-size: 10pt;
font-family: sans-serif;
}
.widget-projects hr {
border-color: #3A1D00;
}
aside p {
margin: 0;
}
</style>

View File

@ -0,0 +1,34 @@
<template>
<div>
<p>
<strong class="sidebar-name">{{ app.name }}</strong><br>
<span v-if="!app.noAboutLink">
<router-link :to="{ name: 'Application', params: { app: app.id } }">About</router-link> &bull;
</span>
<a :title="app.name" :href="app.url">Visit</a>
</p>
<div class="sidebar-description" v-html="app.frontPageText"></div>
</div>
</template>
<script>
export default {
name: 'sidebar-app',
props: ['app'],
data: function () {
return {}
}
}
</script>
<style scoped>
p {
margin: 0;
padding: 0;
}
.sidebar-description {
font-style: italic;
color: #555555;
padding-bottom: 3px;
}
</style>

View File

@ -0,0 +1,43 @@
<template>
<div>
<p class="sidebar-head">
{{ category.name }}
</p>
<sidebar-app v-for="app in appsForCat(category.id)" v-bind:app="app" v-bind:key="app.id" />
</div>
</template>
<script>
import AppData from '../AppData.vue'
import SidebarApp from './SidebarApp.vue'
export default {
name: 'sidebar-category',
props: ['category'],
data: function () {
return {
appsForCat: function (catId) {
return AppData.apps
.filter(app => app.active && app.categoryId === catId)
.sort((a, b) => a.frontPageOrder - b.frontPageOrder)
}
}
},
components: {
SidebarApp
}
}
</script>
<style scoped>
.sidebar-head {
font-family: "Play", "Segoe UI", Ubuntu, "DejaVu Sans", "Liberation Sans", Arial, sans-serif;
font-weight: bold;
color: maroon;
margin: 10px 0;
padding: 3px 0;
display:block;
border-top: solid 1px #3A1D00;
border-bottom: solid 1px #3A1D00;
}
</style>

15
src/main.js Normal file
View File

@ -0,0 +1,15 @@
// 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'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})

24
src/router/index.js Normal file
View File

@ -0,0 +1,24 @@
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import Application from '@/components/Application'
import ApplicationList from '@/components/ApplicationList'
import Linux from '@/components/linux/Linux'
import Averatec from '@/components/linux/Averatec'
import XineRPMs from '@/components/linux/XineRPMs'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{ path: '/', name: 'Home', component: Home },
{ path: '/applications/:app', name: 'Application', component: Application, props: true },
{ path: '/applications', name: 'ApplicationList', component: ApplicationList },
{ path: '/linux/installing-wbel4-rhel4-on-an-averatec-6200-laptop', name: 'Averatec', component: Averatec },
{ path: '/linux/xine-rpms-for-el-x86_64-architecture', name: 'XineRPMs', component: XineRPMs },
{ path: '/linux', name: 'Linux', component: Linux }
]
})

0
static/.gitkeep Normal file
View File

BIN
static/djs-consulting.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
static/screenshots/nsx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
static/screenshots/tcms.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
static/slogan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,26 @@
// A custom Nightwatch assertion.
// the name of the method is the filename.
// can be used in tests like this:
//
// browser.assert.elementCount(selector, count)
//
// for how to write custom assertions see
// http://nightwatchjs.org/guide#writing-custom-assertions
exports.assertion = function (selector, count) {
this.message = 'Testing if element <' + selector + '> has count: ' + count
this.expected = count
this.pass = function (val) {
return val === this.expected
}
this.value = function (res) {
return res.value
}
this.command = function (cb) {
var self = this
return this.api.execute(function (selector) {
return document.querySelectorAll(selector).length
}, [selector], function (res) {
cb.call(self, res)
})
}
}

View File

@ -0,0 +1,46 @@
require('babel-register')
var config = require('../../config')
// http://nightwatchjs.org/gettingstarted#settings-file
module.exports = {
src_folders: ['test/e2e/specs'],
output_folder: 'test/e2e/reports',
custom_assertions_path: ['test/e2e/custom-assertions'],
selenium: {
start_process: true,
server_path: require('selenium-server').path,
host: '127.0.0.1',
port: 4444,
cli_args: {
'webdriver.chrome.driver': require('chromedriver').path
}
},
test_settings: {
default: {
selenium_port: 4444,
selenium_host: 'localhost',
silent: true,
globals: {
devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
}
},
chrome: {
desiredCapabilities: {
browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true
}
},
firefox: {
desiredCapabilities: {
browserName: 'firefox',
javascriptEnabled: true,
acceptSslCerts: true
}
}
}
}

33
test/e2e/runner.js Normal file
View File

@ -0,0 +1,33 @@
// 1. start the dev server using production config
process.env.NODE_ENV = 'testing'
var server = require('../../build/dev-server.js')
server.ready.then(() => {
// 2. run the nightwatch test suite against it
// to run in additional browsers:
// 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
// 2. add it to the --env flag below
// or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
// For more information on Nightwatch's config file, see
// http://nightwatchjs.org/guide#settings-file
var opts = process.argv.slice(2)
if (opts.indexOf('--config') === -1) {
opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
}
if (opts.indexOf('--env') === -1) {
opts = opts.concat(['--env', 'chrome'])
}
var spawn = require('cross-spawn')
var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
runner.on('exit', function (code) {
server.close()
process.exit(code)
})
runner.on('error', function (err) {
server.close()
throw err
})
})

19
test/e2e/specs/test.js Normal file
View File

@ -0,0 +1,19 @@
// For authoring Nightwatch tests, see
// http://nightwatchjs.org/guide#usage
module.exports = {
'default e2e tests': function (browser) {
// automatically uses dev Server port from /config.index.js
// default: http://localhost:8080
// see nightwatch.conf.js
const devServer = browser.globals.devServerURL
browser
.url(devServer)
.waitForElementVisible('#app', 5000)
.assert.elementPresent('.hello')
.assert.containsText('h1', 'Welcome to Your Vue.js App')
.assert.elementCount('img', 1)
.end()
}
}

9
test/unit/.eslintrc Normal file
View File

@ -0,0 +1,9 @@
{
"env": {
"mocha": true
},
"globals": {
"expect": true,
"sinon": true
}
}

13
test/unit/index.js Normal file
View File

@ -0,0 +1,13 @@
import Vue from 'vue'
Vue.config.productionTip = false
// require all test files (files that ends with .spec.js)
const testsContext = require.context('./specs', true, /\.spec$/)
testsContext.keys().forEach(testsContext)
// require all src files except main.js for coverage.
// you can also change this to match only the subset of files that
// you want coverage for.
const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/)
srcContext.keys().forEach(srcContext)

33
test/unit/karma.conf.js Normal file
View File

@ -0,0 +1,33 @@
// This is a karma config file. For more details see
// http://karma-runner.github.io/0.13/config/configuration-file.html
// we are also using it with karma-webpack
// https://github.com/webpack/karma-webpack
var webpackConfig = require('../../build/webpack.test.conf')
module.exports = function (config) {
config.set({
// to run in additional browsers:
// 1. install corresponding karma launcher
// http://karma-runner.github.io/0.13/config/browsers.html
// 2. add it to the `browsers` array below.
browsers: ['PhantomJS'],
frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
reporters: ['spec', 'coverage'],
files: ['./index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
coverageReporter: {
dir: './coverage',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' }
]
}
})
}

0
test/unit/specs/.gitkeep Normal file
View File