checkpoint

This commit is contained in:
Dmitry Belyaev 2021-05-29 18:42:38 +03:00
parent 937785991f
commit 241066587d
Signed by: b4tman
GPG Key ID: 41A00BF15EA7E5F3
12 changed files with 906 additions and 160 deletions

View File

@ -5,10 +5,17 @@
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"mock": "yarn run json-server -S ./test/mock/api -p 17653 -d 1700 -i name -w -r ./test/mock/api/routes.json ./test/mock/api/db.json",
"serve-all": "yarn run concurrently -k \"yarn run serve\" \"yarn run mock\""
},
"dependencies": {
"@popperjs/core": "^2.9.2",
"axios": "^0.21.1",
"bootstrap": "^5.0.1",
"bootstrap-icons": "^1.5.0",
"core-js": "^3.6.5",
"jquery": "^3.6.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
@ -22,9 +29,11 @@
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.1.0",
"concurrently": "^6.2.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0",
"json-server": "^0.16.3",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"prettier": "^2.2.1"

View File

@ -6,6 +6,10 @@
<router-view />
</template>
<script>
export default {};
</script>
<style lang="less">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;

View File

@ -1,130 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
target="_blank"
rel="noopener"
>router</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex"
target="_blank"
rel="noopener"
>vuex</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
>Forum</a
>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
>Community Chat</a
>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
>Twitter</a
>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
>vue-router</a
>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a
href="https://github.com/vuejs/vue-devtools#vue-devtools"
target="_blank"
rel="noopener"
>vue-devtools</a
>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
>vue-loader</a
>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>awesome-vue</a
>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,194 @@
<template>
<div>
<h2>Список баз</h2>
<div v-if="loading_error" class="text-danger m-4">
<span class="fs-1">&#9940;</span><br />
<h3>Ошибка загрузки</h3>
</div>
<div v-else-if="is_loading">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div v-else-if="0 == infobases.length">
<div class="alert alert-warning" role="alert">
<Icon_Exclamation />
<span>Нет ни одной базы</span>
</div>
</div>
<table v-else class="table table-striped">
<thead>
<tr>
<th scope="col" class="col">#</th>
<th scope="col" class="col-lg-6">Имя</th>
<th scope="col" class="col">Ссылка</th>
<th scope="col" class="col">Действия</th>
</tr>
</thead>
<tbody>
<tr v-for="(infobase, index) in infobases" :key="infobase.name">
<th scope="row">{{ index + 1 }}</th>
<td>{{ infobase.name }}</td>
<td>
<template v-if="infobase.publicated">
<form
v-if="is_edit_url_active(infobase.name)"
@submit.prevent="apply_edit_url(infobase.name)"
>
<div class="btn-group shadow rounded-start" role="group">
<input
type="text"
v-model="url_edit[infobase.name]"
class="rounded-start"
/>
<button
type="submit"
class="btn btn-sm btn-primary"
hint="Принять"
>
<Icon_V />
</button>
<button
type="button"
class="btn btn-sm btn-outline-secondary"
@click="cancel_edit_url(infobase.name)"
hint="Отменить"
>
<Icon_X />
</button>
</div>
</form>
<a v-else v-bind:href="url_base + infobase.url" target="blank">{{
infobase.url
}}</a>
</template>
</td>
<td>
<div
v-if="!is_edit_url_active(infobase.name)"
class="btn-group shadow"
role="group"
>
<button
v-if="infobase.publicated"
type="button"
class="btn btn-warning"
@click="start_edit_url(infobase.name)"
hint="Изменить URL"
>
Изменить
</button>
<button
v-if="infobase.publicated"
type="button"
class="btn btn-danger"
@click="remove_publication(infobase.name)"
hint="Снять с публикации"
>
Отменить
</button>
<button
v-else
type="button"
class="btn btn-primary"
@click="publicate(infobase.name)"
hint="Опубликовать базу"
>
Публиковать
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import axios from "axios";
import Icon_V from "@/components/icons/icon-v.vue";
import Icon_X from "@/components/icons/icon-x.vue";
import Icon_Exclamation from "@/components/icons/icon-exclamation.vue";
const api_base = "http://localhost:17653/api/v1";
export default {
name: "InfobaseList",
data: () => ({
url_base: "http://localhost:11111",
is_loading: true,
loading_error: false,
infobases: [],
url_edit: {},
}),
methods: {
publicate(name) {
let infobase = this.infobases.find((infobase) => name === infobase.name);
if (infobase === undefined) return;
infobase.publicated = true;
},
remove_publication(name) {
let infobase = this.infobases.find((infobase) => name === infobase.name);
if (infobase === undefined) return;
infobase.publicated = false;
},
set_url(name, url) {
let infobase = this.infobases.find((infobase) => name === infobase.name);
if (infobase === undefined) return;
infobase.url = url;
},
start_edit_url(name) {
let infobase = this.infobases.find((infobase) => name === infobase.name);
if (infobase === undefined) return;
this.url_edit[name] = infobase.url;
},
cancel_edit_url(name) {
delete this.url_edit[name];
},
apply_edit_url(name) {
this.set_url(name, this.url_edit[name]);
delete this.url_edit[name];
},
is_edit_url_active(name) {
return name in this.url_edit;
},
},
async mounted() {
try {
const res = await axios.get(`${api_base}/infobases`);
if (!res) {
return;
}
const names = res.data;
if (!Array.isArray(names)) {
this.loading_error = true;
return;
}
if (0 < names.length) {
if ("string" !== typeof names[0]) {
this.loading_error = true;
return;
}
}
this.is_loading = false;
this.loading_error = false;
this.infobases = names.map((name) => {
return { name: name, publicated: "bpdemo" === name, url: "/" };
});
} catch (err) {
this.loading_error = true;
}
},
components: {
Icon_V,
Icon_X,
Icon_Exclamation,
},
};
</script>

View File

@ -0,0 +1,16 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
class="bi bi-exclamation-triangle-fill flex-shrink-0 me-2"
viewBox="0 0 16 16"
role="img"
aria-label="Warning:"
>
<path
d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"
/>
</svg>
</template>

View File

@ -0,0 +1,14 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-check-lg"
viewBox="0 0 16 16"
>
<path
d="M13.485 1.431a1.473 1.473 0 0 1 2.104 2.062l-7.84 9.801a1.473 1.473 0 0 1-2.12.04L.431 8.138a1.473 1.473 0 0 1 2.084-2.083l4.111 4.112 6.82-8.69a.486.486 0 0 1 .04-.045z"
/>
</svg>
</template>

View File

@ -0,0 +1,14 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-x-lg"
viewBox="0 0 16 16"
>
<path
d="M1.293 1.293a1 1 0 0 1 1.414 0L8 6.586l5.293-5.293a1 1 0 1 1 1.414 1.414L9.414 8l5.293 5.293a1 1 0 0 1-1.414 1.414L8 9.414l-5.293 5.293a1 1 0 0 1-1.414-1.414L6.586 8 1.293 2.707a1 1 0 0 1 0-1.414z"
/>
</svg>
</template>

View File

@ -3,4 +3,10 @@ import App from "./App.vue";
import router from "./router";
import store from "./store";
import "jquery/src/jquery.js";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.min.js";
window.jQuery = window.$ = require("jquery");
createApp(App).use(store).use(router).mount("#app");

View File

@ -1,18 +1,18 @@
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
<InfobaseList msg="Welcome to Your Vue.js App" />
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
//import HelloWorld from "@/components/HelloWorld.vue";
import InfobaseList from "@/components/InfobaseList.vue";
export default {
name: "Home",
components: {
HelloWorld,
InfobaseList,
},
};
</script>

11
test/mock/api/db.json Normal file
View File

@ -0,0 +1,11 @@
{
"index": ["infobases", "publications", "module", "config"],
"infobases":["test1", "accounting", "bpdemo", "hrm31", "Trade-2021"],
"publications":["accounting", "hrm31"],
"publication":[
{"name": "accounting", "url": "/acc"},
{"name": "hrm31", "url": "/hrm"}
],
"module":{},
"config":{}
}

View File

@ -0,0 +1,7 @@
{
"/api/v1/*": "/$1",
"/": "/index",
"": "/index",
"/publications/:name": "/publication/:name",
"/publications/:name/url": "/publication/:name"
}

651
yarn.lock

File diff suppressed because it is too large Load Diff