commit 6c47a08b39183d35ecc0bfa610bcb8199f767825
parent 65a76571285c33d5fe98d46ac6db38c60a7846c7
Author: Vetle Haflan <vetle@haflan.dev>
Date: Fri, 11 Sep 2020 20:30:29 +0200
Make Vue app template from vuejs experiment
Diffstat:
18 files changed, 89 insertions(+), 419 deletions(-)
diff --git a/vuejs/.gitignore b/vue-app-boilerplate/.gitignore
diff --git a/vue-app-boilerplate/dockerdev.sh b/vue-app-boilerplate/dockerdev.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# Start qumpwebdev container (assuming that qumpweb is a submodule)
+
+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/vue-app-boilerplate/index.html b/vue-app-boilerplate/index.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+ <title>Vue Application</title>
+</head>
+<body>
+ <div id="app"></div>
+ <script src="dist/main.js"></script>
+</body>
+</html>
diff --git a/vue-app-boilerplate/package.json b/vue-app-boilerplate/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "vue-app",
+ "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",
+ "vuex": "^3.1.2",
+ "bootstrap": "^4.4.1"
+ }
+}
diff --git a/vue-app-boilerplate/src/App.vue b/vue-app-boilerplate/src/App.vue
@@ -0,0 +1,16 @@
+<template>
+ <div>
+ Contents here...
+ </div>
+</template>
+
+
+
+<script>
+ export default {
+ name: "App"
+ }
+</script>
+
+<style scoped>
+</style>
diff --git a/vue-app-boilerplate/src/app.js b/vue-app-boilerplate/src/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/vue-app-boilerplate/webpack.config.js b/vue-app-boilerplate/webpack.config.js
@@ -0,0 +1,21 @@
+const glob = require('glob');
+const path = require('path');
+const VueLoaderPlugin = require('vue-loader/lib/plugin');
+
+module.exports = {
+ entry: "./src/app.js",
+ output: {
+ path: path.resolve(__dirname, "./dist/"),
+ filename: "app.js"
+ },
+ module: {
+ rules: [
+ {test: /\.js$/, use: 'babel-loader'},
+ {test: /\.vue$/, use: 'vue-loader'},
+ {test: /\.css$/, use: ['vue-style-loader', 'css-loader']},
+ ]
+ },
+ plugins:[
+ new VueLoaderPlugin()
+ ]
+};
diff --git a/vuejs/dockerdev.sh b/vuejs/dockerdev.sh
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-# Start qumpwebdev container (assuming that qumpweb is a submodule)
-QWD=$PWD/qumpweb
-docker run -d \
- -p 8080:8080 \
- -v $QWD:/app \
- --env-file $QWD/dev/qumpweb_dev.env \
- qumpwebdev
-
-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/index.html b/vuejs/index.html
@@ -1,10 +0,0 @@
-<html>
-<head>
- <title>Vue Experiment</title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
-</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
@@ -1,27 +0,0 @@
-{
- "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/qumpweb b/vuejs/qumpweb
@@ -1 +0,0 @@
-Subproject commit 9edc19517bd43f60ee85a7de05201709a5c6bb58
diff --git a/vuejs/src/App.vue b/vuejs/src/App.vue
@@ -1,68 +0,0 @@
-<template>
- <div class="row" style="margin: 10px;">
- <List :header="'List number one'" :key="'1'">
- <!-- TODO: Consider moving into the actual List component -->
- <Task v-for="(task, index) in tasks" @update="updateTask"
- :index="index"
- :key="task.id"
- :text="task.text"
- @select="selectTask"
- @move="moveTask">
- </Task>
- </List>
- <List :header="'Another list' ":key="'2'"></List>
- </div>
-</template>
-
-
-
-<script>
- // TODO: Move all Qump logic outside of the task components?
- // Perform parsing and generation separately
- // Don't forget that the text area should be editable, though!
- // Unless a UI editor is implemented instead (not sure if I want)
- import axios from 'axios/dist/axios.min.js';
- import 'bootstrap/dist/css/bootstrap.min.css';
- import Task from './components/Task.vue';
- import List from './components/List.vue';
- import qumpToTask from './qumptasks.js';
- export default {
- name: "App",
- components: {List, Task},
- data: function () {
- return {
- qumps: []
- }
- },
- computed: {
- tasks() {
- // https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch
- return this.qumps.map(qumpToTask);
- }
- },
- methods: {
- getData() {
- axios.get("/qumps.json").then(response => {
- this.qumps = response.data;
- });
- },
- updateTask(index, newText) {
- let newItem = this.qumps[index];
- newItem.text = newText;
- this.$set(this.qumps, index, newItem);
- console.log(newText);
- },
- selectTask() {
- },
- moveTask() {
- console.log("Moving task " + this.selected);
- }
- },
- mounted() {
- this.getData();
- }
- }
-</script>
-
-<style scoped>
-</style>
diff --git a/vuejs/src/apps/app.js b/vuejs/src/apps/app.js
@@ -1,10 +0,0 @@
-import Vue from 'vue';
-import App from "../App.vue";
-
-const taskAppData = {};
-
-export const app = new Vue({
- el: "#app",
- render: h => h(App),
- data: taskAppData,
-});
diff --git a/vuejs/src/components/Checkbox.vue b/vuejs/src/components/Checkbox.vue
@@ -1,37 +0,0 @@
-<template>
- <div>
- <input type="checkbox" @change="$emit('update')" :checked="checked" />
- <span v-html="html"></span>
- </div>
-</template>
-
-<script>
- export default {
- name: "Checkbox",
- props: {
- contents: String
- },
- data() {
- let match = this.contents.match(/^ *- *\[[ x]*\]/);
- return {
- checked: match[0].includes("x"),
- html: this.contents.replace(match[0], "")
- }
- }
- }
-</script>
-
-<style scoped>
- span {
- white-space: pre-wrap;
- }
- input {
- /* Double-sized Checkboxes */
- -ms-transform: scale(1.5); /* IE */
- -moz-transform: scale(1.5); /* FF */
- -webkit-transform: scale(1.5); /* Safari and Chrome */
- -o-transform: scale(1.5); /* Opera */
- transform: scale(1.5);
- padding: 10px;
- }
-</style>
diff --git a/vuejs/src/components/List.vue b/vuejs/src/components/List.vue
@@ -1,63 +0,0 @@
-<template>
- <div class="col col-12 col-md-6 col-lg-4 col-xl-3">
- <div class="card list-card"
- ondragover="event.preventDefault();"
- v-on:drop="moveTask">
- <div class="list-title">
- {{header}}
- <button @click="collapsed = !collapsed" type="button" class="float-right btn btn-info btn-sm">
- {{ collapsed ? 'v' : '^' }}
- </button>
- </div>
- <div v-if="!collapsed" class="card-text">
- <slot></slot>
- <button type="button" class="btn btn-primary">+</button>
- <button type="button" class="btn btn-primary">^</button>
- <button type="button" class="btn btn-primary">></button>
- </div>
- </div>
- </div>
-</template>
-
-
-
-<script>
- import 'bootstrap/dist/css/bootstrap.min.css';
- export default {
- name: "List",
- props: {
- header: String,
- },
- data() {
- return {
- collapsed: true
- }
- },
- computed: {
- style() {
- return "background-color: " + this.color;
- }
- },
- methods: {
- moveTask(event) {
- console.log("Dropped task on list " + this.header);
- console.log(event);
- },
- }
- }
-</script>
-
-<style scoped>
- .list-title{
- margin: 10px;
- font-weight: bold;
- }
- .list-card {
- padding: 5px;
- border-color: black;
- background-color: #EEE;
- }
- .card-text {
- width: 100%;
- }
-</style>
diff --git a/vuejs/src/components/RawText.vue b/vuejs/src/components/RawText.vue
@@ -1,18 +0,0 @@
-<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
@@ -1,138 +0,0 @@
-<template>
- <!-- TODO: Instead of dbclick - make first click select task and second click activate edit -->
-
- <div class="card"
- @dblclick="editToggle"
- @keyup.ctrl.enter="editToggle"
- @keyup.enter="enterAction"
- draggable="true"
- v-on:dragstart="$emit('move', index)">
- <template v-if="editing">
- <textarea ref="editor"
- v-model="contents"
- v-bind:rows="textRows"></textarea>
- </template>
- <template v-else>
- <component v-for="component in renderedComponents"
- :key="component.id"
- :is="component.name"
- :contents="component.contents"
- @update="updateTask"></component>
- </template>
- <!-- NOTE: This dot menu might not be necessary.
- Simply clicking the task should be sufficient -->
- <span class="dot-menu">...</span>
- </div>
-</template>
-
-<script>
- import 'bootstrap/dist/css/bootstrap.min.css';
- import axios from 'axios/dist/axios.min.js';
- import RawText from './RawText.vue';
- import Checkbox from './Checkbox.vue';
- export default {
- name: "Task",
- components: {RawText, Checkbox},
- 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 = {
- id: i,
- name: "RawText"
- };
- let line = lines[i];
- // TODO: Make more generic, like an array of objects w/
- // component name, parser/modifier and regex to match on
- if (/^ *- *\[[ x]*\]/.test(lines[i])) {
- comp.name = "Checkbox";
- } else if (/^ *- /.test(lines[i])) {
- // TODO: Consider implementing unordered list
- let match = line.match(/^ *-(.+)/);
- if (match) {
- line = "<li>" + match[1] + "</li>";
- }
- } else if (line === "") {
- // TODO: Find a more elegant way of dealing with '\n's
- line = "\n";
- }
- let match = line.match(/\*(.+)\*/);
- if (match) {
- line = line.replace(
- match[0], "<b>" + match[1] + "</b>"
- )
- }
- comp.contents = line;
- 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);
- } else {
- let refs = this.$refs;
- console.log(refs.editor);//.focus();
- }
- },
- 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 if (!e.ctrlKey) {
- this.contents += match[0] + " ";
- }
- }
- },
- updateTask(e) {
- // TODO: Generate qump text based on the different components
- console.log(e);
- }
- }
- }
- // TODO: Compile all regexs
-</script>
-
-<style scoped>
- div {
- width: auto;
- padding: 5px;
- margin-top: 2px;
- margin-bottom: 2px;
- }
- span.dot-menu {
- margin-left: auto;
- font-size:12px;
- padding:0;
- position: absolute;
- right: 5px;
- margin:0;
- cursor: pointer;
- }
- textarea {
- width: 100%;
- font-family: monospace;
- }
-</style>
diff --git a/vuejs/webpack.config.js b/vuejs/webpack.config.js
@@ -1,29 +0,0 @@
-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, "./qumpweb/static/apps/"),
- 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'
- }
-};