Skip to content

Commit 1718b2b

Browse files
committed
add promise button
1 parent 98e0e79 commit 1718b2b

File tree

6 files changed

+547
-68
lines changed

6 files changed

+547
-68
lines changed

.eslintrc.js

+22-26
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
11
module.exports = {
2-
root: true,
3-
env: {
4-
node: true
5-
},
6-
'extends': [
7-
'plugin:vue/essential',
8-
'@vue/standard',
9-
'@vue/typescript'
10-
],
11-
rules: {
12-
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
13-
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
14-
},
15-
parserOptions: {
16-
parser: '@typescript-eslint/parser'
17-
},
18-
overrides: [
19-
{
20-
files: [
21-
'**/__tests__/*.{j,t}s?(x)'
22-
],
23-
env: {
24-
jest: true
25-
}
2+
"env": {
3+
"browser": true,
4+
"es6": true
5+
},
6+
"extends": [
7+
"plugin:vue/essential"
8+
],
9+
"globals": {
10+
"Atomics": "readonly",
11+
"SharedArrayBuffer": "readonly"
12+
},
13+
"parserOptions": {
14+
"ecmaVersion": 2018,
15+
"parser": "@typescript-eslint/parser",
16+
"sourceType": "module"
17+
},
18+
"plugins": [
19+
"vue",
20+
"@typescript-eslint"
21+
],
22+
"rules": {
2623
}
27-
]
28-
}
24+
};

package.json

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
11
{
2-
"name": "promise-button",
2+
"name": "vue-promise-button",
3+
"description": "A promise button for vuejs",
34
"version": "0.1.0",
45
"private": true,
6+
"main": "./dist/vue-promise-button.common.js",
57
"scripts": {
68
"serve": "vue-cli-service serve",
79
"build": "vue-cli-service build",
10+
"build-bundle": "vue-cli-service build --target lib --name vue-promise-button ./src/components/PromiseButton.vue",
811
"lint": "vue-cli-service lint",
912
"test:unit": "vue-cli-service test:unit"
1013
},
14+
"files": [
15+
"dist/*",
16+
"src/*",
17+
"package.json"
18+
],
19+
"keywords": [
20+
"promise",
21+
"vue-promise",
22+
"promise-button",
23+
"vue-promise-button"
24+
],
25+
"license": "MIT",
26+
"author": "mihnsen <[email protected]> (https://github.com/mihnsen/)",
1127
"dependencies": {
28+
"bootstrap": "^4.3.1",
1229
"core-js": "^2.6.5",
1330
"vue": "^2.6.10",
1431
"vue-class-component": "^7.0.2",
1532
"vue-property-decorator": "^8.1.0"
1633
},
1734
"devDependencies": {
1835
"@types/jest": "^23.1.4",
36+
"@typescript-eslint/eslint-plugin": "^2.3.1-alpha.1",
37+
"@typescript-eslint/parser": "^2.3.0",
1938
"@vue/cli-plugin-babel": "^3.11.0",
2039
"@vue/cli-plugin-eslint": "^3.11.0",
2140
"@vue/cli-plugin-typescript": "^3.11.0",
@@ -27,7 +46,9 @@
2746
"babel-core": "7.0.0-bridge.0",
2847
"babel-eslint": "^10.0.1",
2948
"eslint": "^5.16.0",
30-
"eslint-plugin-vue": "^5.0.0",
49+
"eslint-plugin-vue": "^5.2.3",
50+
"pug": "^2.0.4",
51+
"pug-plain-loader": "^1.0.0",
3152
"sass": "^1.18.0",
3253
"sass-loader": "^7.1.0",
3354
"ts-jest": "^23.0.0",

src/components/HelloWorld.vue

+38-30
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,44 @@
11
<template>
22
<div class="hello">
3-
<h1>{{ msg }}</h1>
4-
<p>
5-
For a guide and recipes on how to configure / customize this project,<br>
6-
check out the
7-
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
8-
</p>
9-
<h3>Installed CLI Plugins</h3>
10-
<ul>
11-
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
12-
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
13-
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
14-
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest" target="_blank" rel="noopener">unit-jest</a></li>
15-
</ul>
16-
<h3>Essential Links</h3>
17-
<ul>
18-
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
19-
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
20-
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
21-
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
22-
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
23-
</ul>
24-
<h3>Ecosystem</h3>
25-
<ul>
26-
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
27-
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
28-
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
29-
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
30-
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
31-
</ul>
3+
<h2>{{ msg }}</h2>
4+
5+
<div style="margin-bottom: 20px">
6+
<PromiseButton class="btn" :promise="fakePromise">Success promise</PromiseButton>
7+
</div>
8+
<div>
9+
<PromiseButton class="btn" :promise="failurePromise">Failure promise</PromiseButton>
10+
</div>
3211
</div>
3312
</template>
3413

3514
<script lang="ts">
3615
import { Component, Prop, Vue } from 'vue-property-decorator'
16+
import PromiseButton from './PromiseButton.vue'
3717
38-
@Component
18+
@Component({
19+
components: {
20+
PromiseButton,
21+
}
22+
})
3923
export default class HelloWorld extends Vue {
24+
4025
@Prop() private msg!: string;
26+
27+
fakePromise() {
28+
return new Promise((resolve: any, reject: any) => {
29+
setTimeout(() => {
30+
resolve(true);
31+
}, 2000);
32+
});
33+
}
34+
35+
failurePromise() {
36+
return new Promise((resolve: any, reject: any) => {
37+
setTimeout(() => {
38+
reject(new Error('This promise failure'));
39+
}, 2000);
40+
});
41+
}
4142
}
4243
</script>
4344

@@ -57,4 +58,11 @@ li {
5758
a {
5859
color: #42b983;
5960
}
61+
62+
.btn {
63+
padding: 5px 15px;
64+
background: rgba(0, 0, 0, .05);
65+
border: 1px solid rgba(0, 0, 0, 1);
66+
outline: none;
67+
}
6068
</style>

src/components/PromiseButton.vue

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<template lang="pug">
2+
button.promise-button(
3+
type="button",
4+
@click.stop="handle",
5+
:class="{ 'promise-button--notext': !isShowText }"
6+
)
7+
span(v-if="isShowText")
8+
slot
9+
span.promise-button-text
10+
slot(name="spinner")
11+
span.promise-button-spinner(
12+
v-show="isProcessing || forceProcessing",
13+
role="status",
14+
)
15+
span.sr-only Loading...
16+
</template>
17+
<script lang="ts">
18+
import { Component, Prop, Vue } from 'vue-property-decorator';
19+
20+
@Component
21+
export default class PromiseButton extends Vue {
22+
@Prop({ type: Function, required: true })
23+
promise!: Function
24+
25+
@Prop({ type: Boolean, default: false })
26+
autoHide!: boolean
27+
28+
@Prop({ type: Boolean, default: false })
29+
forceProcessing!: boolean
30+
31+
isProcessing: boolean = false;
32+
33+
/**
34+
* get computed of show text or not
35+
*/
36+
get isShowText() {
37+
if (this.isProcessing) {
38+
return !this.autoHide;
39+
}
40+
41+
return true;
42+
}
43+
44+
/**
45+
* main handle function
46+
*/
47+
handle() {
48+
if (!this.isProcessing) {
49+
this.isProcessing = true;
50+
this.promise()
51+
.catch((e: Error) => { // eslint-disable-line
52+
this.isProcessing = false;
53+
throw e;
54+
})
55+
.then(() => {
56+
this.isProcessing = false;
57+
});
58+
}
59+
}
60+
};
61+
</script>
62+
<style lang="sass" scoped>
63+
@import '~bootstrap/scss/functions'
64+
@import '~bootstrap/scss/variables'
65+
@import '~bootstrap/scss/mixins'
66+
67+
@import '~bootstrap/scss/utilities/screenreaders'
68+
@import '~bootstrap/scss/spinners'
69+
70+
.promise-button
71+
display: inline-flex
72+
73+
.promise-button-spinner
74+
@extend .spinner-border
75+
width: 1em
76+
height: 1em
77+
border-width: .15em
78+
margin-left: .5em
79+
80+
</style>

vue.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
css: {
3+
extract: false
4+
}
5+
};

0 commit comments

Comments
 (0)