experiments

All kinds of coding experiments
Log | Files | Refs | Submodules

commit 1818f18565808edeb049766dfe2de95df9f29c07
parent a97c7c7d9c05cea1019348f45bf27dc49008df3e
Author: Vetle Haflan <vetle@haflan.dev>
Date:   Sat, 11 Jan 2020 04:48:59 +0100

Add Trello inspired Vue project

Diffstat:
Avuejs/.gitignore | 2++
Avuejs/dockerdev.sh | 10++++++++++
Avuejs/exdata.json | 9+++++++++
Avuejs/index.html | 9+++++++++
Avuejs/package.json | 27+++++++++++++++++++++++++++
Avuejs/src/App.vue | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Avuejs/src/apps/app.js | 7+++++++
Avuejs/src/components/RawText.vue | 18++++++++++++++++++
Avuejs/src/components/Task.vue | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avuejs/webpack.config.js | 30++++++++++++++++++++++++++++++
10 files changed, 268 insertions(+), 0 deletions(-)

diff --git a/vuejs/.gitignore b/vuejs/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/vuejs/dockerdev.sh b/vuejs/dockerdev.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKERCMD="docker run -it -v $PWD:/vue -w /vue node:alpine /bin/sh -c " + +if [ ! -d "node_modules" ]; then + $DOCKERCMD "npm install; npm run build-dev" +else + $DOCKERCMD "npm run build-dev" +fi + diff --git a/vuejs/exdata.json b/vuejs/exdata.json @@ -0,0 +1,9 @@ +[{ + "id": "42", + "text": "/todo this is my great todo" +}, +{ + "id": "45", + "text": "/todo is my other" + +}] diff --git a/vuejs/index.html b/vuejs/index.html @@ -0,0 +1,9 @@ +<html> +<head> + <title>Vue Experiment</title> +</head> +<body style="background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Mont_Blanc_oct_2004.JPG/1024px-Mont_Blanc_oct_2004.JPG');"> + <div id="app"></div> + <script src="dist/app.js"></script> +</body> +</html> diff --git a/vuejs/package.json b/vuejs/package.json @@ -0,0 +1,27 @@ +{ + "name": "tester", + "version": "1.0.0", + "scripts": { + "clean": "rimraf ./dist/", + "build": "npm run clean && webpack --config webpack.config.js --mode production", + "build-dev": "npm run clean && webpack --config webpack.config.js --mode development --watch" + }, + "dependencies": {}, + "devDependencies": { + "vue": "^2.6.10", + "vue-loader": "^15.7.2", + "vue-template-compiler": "^2.6.10", + "@babel/core": "^7.7.5", + "@babel/preset-env": "^7.7.6", + "babel-loader": "^8.0.6", + "css-loader": "^3.3.0", + "rimraf": "^3.0.0", + "webpack": "^4.41.2", + "webpack-cli": "^3.3.10", + "sass-loader": "^8.0.0", + "node-sass": "^4.13.0", + "vuex": "^3.1.2", + "bootstrap": "^4.4.1", + "axios": "^0.19.1" + } +} diff --git a/vuejs/src/App.vue b/vuejs/src/App.vue @@ -0,0 +1,49 @@ +<template> + <div> + <!-- <List></List> --> + <div class="card" style="width: 400px; background-color: #DFF"> + <b @onhover="alert('hah')">This workin?</b> + <Task v-for="(item, index) in exArray" @update="updateTask" + :key="item.id" + :index="index" + :text="item.text"> + </Task> + </div> + </div> +</template> + + + +<script> + import axios from 'axios/dist/axios.min.js'; + import 'bootstrap/dist/css/bootstrap.min.css'; + import Task from './components/Task.vue'; + export default { + name: "App", + components: {Task}, + data: function () { + return { + exArray: [] + } + }, + methods: { + getData() { + axios.get("/exdata.json").then(response => { + this.exArray = response.data; + console.log(response.data) + }); + }, + updateTask(index, newText) { + let newItem = this.exArray[index]; + newItem.text = newText + this.$set(this.exArray, index, newItem); + } + }, + mounted() { + this.getData(); + } + } +</script> + +<style scoped> +</style> diff --git a/vuejs/src/apps/app.js b/vuejs/src/apps/app.js @@ -0,0 +1,7 @@ +import Vue from 'vue'; +import App from "../App.vue"; + +export const app = new Vue({ + el: "#app", + render: h => h(App), +}); diff --git a/vuejs/src/components/RawText.vue b/vuejs/src/components/RawText.vue @@ -0,0 +1,18 @@ +<template> + <span v-html="contents"></span> +</template> + +<script> + export default { + name: "RawText", + props: { + contents: String + } + } +</script> + +<style scoped> + span { + white-space: pre-wrap; + } +</style> diff --git a/vuejs/src/components/Task.vue b/vuejs/src/components/Task.vue @@ -0,0 +1,107 @@ +<template> + <div class="card" + @dblclick="editToggle" + @keyup.ctrl.enter="editToggle" + @keyup.enter="enterAction"> + <template v-if="editing"> + <textarea v-model="contents" v-bind:rows="textRows"></textarea> + </template> + <template v-else> + <component v-for="component in renderedComponents" + :is="component.name" + :contents="component.contents"></component> + </template> + </div> +</template> + +<script> + import 'bootstrap/dist/css/bootstrap.min.css'; + import axios from 'axios/dist/axios.min.js'; + import RawText from './RawText.vue'; + export default { + name: "Task", + components: {RawText}, + props: { + index: Number, + text: String + }, + data() { + return { + editing: false, + contents: this.text, + } + }, + computed: { + renderedComponents() { + let components = []; + let lines = this.contents.split("\n"); + for (var i in lines) { + // If line starts starts with '- ': + let comp = { + name: "RawText", + contents: lines[i] + }; + // TODO: Make more generic, like an array of objects w/ + // component name, parser/modifier and regex to match on + if (/^ *\/todo +/.test(lines[i])) { + comp.contents = lines[i].replace(/\/todo /, ''); + } else if (/^- /.test(lines[i])) { + // TODO: Consider implementing unordered list + } else if (/^ *- *\[ *\]/.test(lines[i])) { + comp.name = "Checkbox" + console.log("check") + } else if (lines[i] === "") { + // TODO: Find a more elegant way of dealing with '\n's + comp.contents = "\n"; + } + let match = lines[i].match(/\*(.+)\*/); + if (match) { + comp.contents = lines[i].replace( + match[0], "<b>" + match[1] + "</b>" + ) + } + components.push(comp); + } + return components; + }, + textRows() { + return this.contents.split("\n").length; + } + }, + methods: { + editToggle() { + this.editing = !this.editing; + if (!this.editing) { + this.$emit("update", this.index, this.contents); + } + }, + enterAction(e) { + // If last line starts with '- [ ]', this one should too + // TODO: Allow Shift+Enter to exit checkbox mode + let lines = this.contents.split("\n"); + let match = lines[lines.length-2].match(/^ *- *\[ *\]/); + if (match) { + if (e.shiftKey) { + this.contents += " ".repeat(match[0].length) + " "; + } else { + this.contents += match[0] + " "; + } + } + } + } + } + // TODO: Compile all regexs +</script> + +<style scoped> + div { + width: auto; + padding: 5px; + margin-top: 2px; + margin-bottom: 2px; + } + textarea { + width: 100%; + font-family: monospace; + } +</style> diff --git a/vuejs/webpack.config.js b/vuejs/webpack.config.js @@ -0,0 +1,29 @@ +const glob = require('glob'); +const path = require('path'); +const VueLoaderPlugin = require('vue-loader/lib/plugin'); + +module.exports = { + entry: glob.sync('./src/apps/**.js').reduce((obj, el) => { + obj[path.parse(el).name] = el; + return obj; + },{}), + output: { + path: path.resolve(__dirname, "./dist/"), + filename: "[name].js" + }, + module: { + rules: [ + {test: /\.js$/, use: 'babel-loader'}, + {test: /\.vue$/, use: 'vue-loader'}, + {test: /\.css$/, use: ['vue-style-loader', 'css-loader']}, + {test: /\.scss$/, use: ['vue-style-loader', 'css-loader', 'sass-loader']} + ] + }, + plugins:[ + new VueLoaderPlugin() + ], + externals:{ + jquery: 'jQuery', + axios: 'axios' + } +};+ \ No newline at end of file