Skip to content
This repository was archived by the owner on May 16, 2022. It is now read-only.

Commit 6dea095

Browse files
committed
Placeholder input
1 parent 82dd518 commit 6dea095

File tree

5 files changed

+577
-5
lines changed

5 files changed

+577
-5
lines changed

src/assets/main.scss

+1
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,4 @@ $message-header-background-color: $not-quite-black;
129129

130130
$background: $white;
131131
@import "~buefy/src/scss/buefy";
132+
@import "placeholderInput.scss"

src/assets/placeholderInput.scss

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
.placeholder-input {
2+
position: relative;
3+
.dropdown-menu {
4+
display: block;
5+
min-width: 100%;
6+
max-width: 100%;
7+
&.is-opened-top {
8+
top: auto;
9+
bottom: 100%;
10+
padding-bottom: 4px;
11+
}
12+
}
13+
.dropdown-content {
14+
overflow: auto;
15+
max-height: 200px;
16+
}
17+
.dropdown-item {
18+
white-space: nowrap;
19+
overflow: hidden;
20+
text-overflow: ellipsis;
21+
&.is-hovered {
22+
background: $dropdown-item-hover-background-color;
23+
color: $dropdown-item-hover-color;
24+
}
25+
&.is-disabled {
26+
opacity: 0.5;
27+
cursor: not-allowed;
28+
}
29+
}
30+
&.is-small {
31+
@include control-small;
32+
}
33+
&.is-medium{
34+
@include control-medium;
35+
}
36+
&.is-large {
37+
@include control-large;
38+
}
39+
}

src/components/dashboard/modules/DashboardJoinLockModal.vue

+25-5
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@
66
</header>
77
<section class="modal-card-body">
88
<b-field label="Kick message">
9-
<b-input
9+
<PlaceholderInput
1010
v-model="moduleValues.message"
11+
field="name"
12+
:data="validPlaceholders"
1113
:maxlength="module.input.message.max"
12-
type="textarea"
1314
placeholder="You've been kicked from {server} because the join lock is enabled. Please try joining again later.">
14-
</b-input>
15+
<template slot="header">
16+
<strong class="placeholder-header">Placeholders</strong>
17+
</template>
18+
<template slot-scope="props">
19+
<span v-pre>{</span>{{ props.option.name }}<span v-pre>}</span>
20+
<small>{{ props.option.description }}</small>
21+
</template>
22+
<template slot="empty" slot-scope="props">
23+
No results found for {{ props.value }}
24+
</template>
25+
</PlaceholderInput>
1526
</b-field>
1627
</section>
1728
<footer class="modal-card-foot module-card-footer">
@@ -22,14 +33,21 @@
2233

2334
<script>
2435
import _ from 'lodash'
36+
import PlaceholderInput from '../util/PlaceholderInput'
2537
2638
export default {
2739
name: 'DashboardJoinLockModal',
2840
props: [ 'guild', 'module', 'saveCallback' ],
41+
components: { PlaceholderInput },
2942
data () {
3043
return {
3144
saving: false,
32-
moduleValues: JSON.parse(JSON.stringify(this.module.values))
45+
moduleValues: JSON.parse(JSON.stringify(this.module.values)),
46+
// TODO: Backend placeholder handler
47+
validPlaceholders: [{
48+
name: 'server',
49+
description: 'Name of the server'
50+
}]
3351
}
3452
},
3553
computed: {
@@ -47,5 +65,7 @@ export default {
4765
</script>
4866

4967
<style scoped>
50-
68+
.placeholder-header {
69+
color: white;
70+
}
5171
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
export default {
2+
props: {
3+
size: String,
4+
expanded: Boolean,
5+
loading: Boolean,
6+
rounded: Boolean,
7+
icon: String,
8+
iconPack: String,
9+
// Native options to use in HTML5 validation
10+
autocomplete: String,
11+
maxlength: [Number, String],
12+
useHtml5Validation: {
13+
type: Boolean,
14+
default: () => true
15+
},
16+
validationMessage: String
17+
},
18+
data () {
19+
return {
20+
isValid: true,
21+
isFocused: false,
22+
newIconPack: this.iconPack || 'mdi'
23+
}
24+
},
25+
computed: {
26+
/**
27+
* Find parent Field, max 3 levels deep.
28+
*/
29+
parentField () {
30+
let parent = this.$parent
31+
for (let i = 0; i < 3; i++) {
32+
if (parent && !parent.$data._isField) {
33+
parent = parent.$parent
34+
}
35+
}
36+
return parent
37+
},
38+
39+
/**
40+
* Get the type prop from parent if it's a Field.
41+
*/
42+
statusType () {
43+
if (!this.parentField) return
44+
if (!this.parentField.newType) return
45+
if (typeof this.parentField.newType === 'string') {
46+
return this.parentField.newType
47+
} else {
48+
for (let key in this.parentField.newType) {
49+
if (this.parentField.newType[key]) {
50+
return key
51+
}
52+
}
53+
}
54+
},
55+
56+
/**
57+
* Get the message prop from parent if it's a Field.
58+
*/
59+
statusMessage () {
60+
if (!this.parentField) return
61+
62+
return this.parentField.newMessage
63+
},
64+
65+
/**
66+
* Fix icon size for inputs, large was too big
67+
*/
68+
iconSize () {
69+
switch (this.size) {
70+
case 'is-small': return this.size
71+
case 'is-medium': return
72+
case 'is-large': return this.newIconPack === 'mdi'
73+
? 'is-medium'
74+
: ''
75+
}
76+
}
77+
},
78+
methods: {
79+
/**
80+
* Focus method that work dynamically depending on the component.
81+
*/
82+
focus () {
83+
if (this.$data._elementRef === undefined) return
84+
85+
this.$nextTick(() => {
86+
const el = this.$el.querySelector(this.$data._elementRef)
87+
if (el) el.focus()
88+
})
89+
},
90+
91+
onBlur ($event) {
92+
this.isFocused = false
93+
this.$emit('blur', $event)
94+
this.checkHtml5Validity()
95+
},
96+
97+
onFocus ($event) {
98+
this.isFocused = true
99+
this.$emit('focus', $event)
100+
},
101+
102+
getElement () {
103+
return this.$el.querySelector(this.$data._elementRef)
104+
},
105+
106+
setInvalid () {
107+
let type = 'is-danger'
108+
let message = this.validationMessage || this.getElement().validationMessage
109+
this.setValidity(type, message)
110+
},
111+
112+
setValidity (type, message) {
113+
this.$nextTick(() => {
114+
if (this.parentField) {
115+
// Set type only if not defined
116+
if (!this.parentField.type) {
117+
this.parentField.newType = type
118+
}
119+
// Set message only if not defined
120+
if (!this.parentField.message) {
121+
this.parentField.newMessage = message
122+
}
123+
}
124+
})
125+
},
126+
127+
/**
128+
* Check HTML5 validation, set isValid property.
129+
* If validation fail, send 'is-danger' type,
130+
* and error message to parent if it's a Field.
131+
*/
132+
checkHtml5Validity () {
133+
if (!this.useHtml5Validation) return
134+
135+
if (this.$refs[this.$data._elementRef] === undefined) return
136+
137+
if (!this.getElement().checkValidity()) {
138+
this.setInvalid()
139+
this.isValid = false
140+
} else {
141+
this.setValidity(null, null)
142+
this.isValid = true
143+
}
144+
145+
return this.isValid
146+
}
147+
}
148+
}

0 commit comments

Comments
 (0)