Page MenuHomePhorge

D1120.1775440694.diff
No OneTemporary

Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None

D1120.1775440694.diff

diff --git a/src/resources/js/app.js b/src/resources/js/app.js
--- a/src/resources/js/app.js
+++ b/src/resources/js/app.js
@@ -82,18 +82,16 @@
let feedback = $('<div class="invalid-feedback">').text(msg_text)
- if (input.is('.listinput')) {
+ if (input.is('.list-input')) {
// List input widget
- let list = input.next('.listinput-widget')
-
- list.children(':not(:first-child)').each((index, element) => {
+ input.children(':not(:first-child)').each((index, element) => {
if (msg[index]) {
$(element).find('input').addClass('is-invalid')
}
})
- list.addClass('is-invalid').next('.invalid-feedback').remove()
- list.after(feedback)
+ input.addClass('is-invalid').next('.invalid-feedback').remove()
+ input.after(feedback)
}
else {
// Standard form element
diff --git a/src/resources/js/fontawesome.js b/src/resources/js/fontawesome.js
--- a/src/resources/js/fontawesome.js
+++ b/src/resources/js/fontawesome.js
@@ -13,6 +13,7 @@
faInfoCircle,
faLock,
faKey,
+ faPlus,
faSignInAlt,
faSyncAlt,
faTrashAlt,
@@ -30,6 +31,7 @@
faInfoCircle,
faLock,
faKey,
+ faPlus,
faSignInAlt,
faSquare,
faSyncAlt,
diff --git a/src/resources/sass/app.scss b/src/resources/sass/app.scss
--- a/src/resources/sass/app.scss
+++ b/src/resources/sass/app.scss
@@ -79,11 +79,7 @@
font-weight: bold;
}
-.listinput {
- display: none;
-}
-
-.listinput-widget {
+.list-input {
& > div {
&:not(:last-child) {
margin-bottom: -1px;
@@ -103,6 +99,10 @@
}
}
}
+
+ input.is-invalid {
+ z-index: 2;
+ }
}
.range-input {
diff --git a/src/resources/vue/User/Info.vue b/src/resources/vue/User/Info.vue
--- a/src/resources/vue/User/Info.vue
+++ b/src/resources/vue/User/Info.vue
@@ -31,9 +31,9 @@
</div>
</div>
<div class="form-group row">
- <label for="aliases" class="col-sm-4 col-form-label">Email aliases</label>
+ <label for="aliases-input" class="col-sm-4 col-form-label">Email aliases</label>
<div class="col-sm-8">
- <textarea class="form-control listinput" id="aliases"></textarea>
+ <list-input id="aliases" v-bind:list="user.aliases"></list-input>
</div>
</div>
<div class="form-group row">
@@ -147,7 +147,12 @@
</template>
<script>
+ import ListInput from '../Widgets/ListInput'
+
export default {
+ components: {
+ ListInput,
+ },
data() {
return {
discount: 0,
@@ -190,8 +195,6 @@
this.user.last_name = response.data.settings.last_name
this.discount = this.user.wallet.discount
this.discount_description = this.user.wallet.discount_description
- $('#aliases').val(response.data.aliases.join("\n"))
- listinput('#aliases')
axios.get('/api/v4/skus')
.then(response => {
@@ -220,18 +223,12 @@
}
},
mounted() {
- if (this.user_id === 'new') {
- listinput('#aliases')
- }
-
$('#first_name').focus()
},
methods: {
submit() {
this.$root.clearFormValidation($('#user-info form'))
- this.user.aliases = $('#aliases').val().split("\n")
-
let method = 'post'
let location = '/api/v4/users'
@@ -360,76 +357,4 @@
}
}
}
-
- // List widget
- // TODO: move it to a separate component file when needed
- function listinput(elem)
- {
- elem = $(elem).addClass('listinput');
-
- let widget = $('<div class="listinput-widget">')
- let main_row = $('<div class="input-group">')
- let wrap = $('<div class="input-group-append">')
- let input = $('<input type="text" class="form-control main-input">')
- let add_btn = $('<a href="#" class="btn btn-outline-secondary">').text('Add')
-
- let update = () => {
- let value = []
-
- widget.find('input:not(.main-input)').each((index, input) => {
- if (input.value) {
- value.push(input.value)
- }
- })
-
- elem.val(value.join("\n"))
- }
-
- let add_func = (value) => {
- let row = $('<div class="input-group">')
- let rinput = $('<input type="text" class="form-control">').val(value)
- let rwrap = $('<div class="input-group-append">')
- let del_btn = $('<a href="#" class="btn btn-outline-secondary">')
- .text('Remove')
- .on('click', e => {
- row.remove()
- input.focus()
- update()
- })
-
- widget.append(row.append(rinput).append(rwrap.append(del_btn)))
- }
-
- // Create the widget and add to DOM
- widget.append(main_row.append(input).append(wrap.append(add_btn)))
- .insertAfter(elem)
-
- // Add rows for every line in the original textarea
- let value = $.trim(elem.val())
- if (value.length) {
- value.split("\n").forEach(add_func)
- }
-
- // Click handler on the Add button
- add_btn.on('click', e => {
- let value = input.val()
-
- if (!value) {
- return;
- }
-
- input.val('').focus();
- add_func(value)
- update()
- })
-
- // Enter key handler on main input
- input.on('keydown', function(e) {
- if (e.which == 13 && this.value) {
- add_btn.click()
- return false
- }
- })
- }
-
</script>
diff --git a/src/resources/vue/Widgets/ListInput.vue b/src/resources/vue/Widgets/ListInput.vue
new file mode 100644
--- /dev/null
+++ b/src/resources/vue/Widgets/ListInput.vue
@@ -0,0 +1,55 @@
+<template>
+ <div class="list-input" :id="id">
+ <div class="input-group">
+ <input :id="id + '-input'" type="text" class="form-control main-input" @keydown="keyDown">
+ <div class="input-group-append">
+ <a href="#" class="btn btn-outline-secondary" @click="addItem">
+ <svg-icon icon="plus"></svg-icon>
+ <span class="sr-only">Add</span>
+ </a>
+ </div>
+ </div>
+ <div class="input-group" v-for="(item, index) in list" :key="index">
+ <input type="text" class="form-control" :value="item">
+ <div class="input-group-append">
+ <a href="#" class="btn btn-outline-secondary" @click="deleteItem(index)">
+ <svg-icon icon="trash-alt"></svg-icon>
+ <span class="sr-only">Delete</span>
+ </a>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+ export default {
+ props: {
+ 'list': { type: Array, default: () => [] },
+ 'id': { type: String, default: '' }
+ },
+ methods: {
+ addItem() {
+ let input = $(this.$el).find('.main-input')
+ let value = input.val()
+
+ if (value) {
+ this.list.push(value)
+ input.val('').focus()
+ }
+ },
+ deleteItem(index) {
+ this.$delete(this.list, index)
+
+ if (this.list.length == 1) {
+ $(this.$el).removeClass('is-invalid')
+ }
+ },
+ keyDown(e) {
+ if (e.which == 13 && e.target.value) {
+ this.addItem()
+ e.preventDefault()
+ }
+ }
+ }
+ }
+</script>
diff --git a/src/tests/Browser/Components/ListInput.php b/src/tests/Browser/Components/ListInput.php
--- a/src/tests/Browser/Components/ListInput.php
+++ b/src/tests/Browser/Components/ListInput.php
@@ -22,7 +22,7 @@
*/
public function selector()
{
- return $this->selector . ' + .listinput-widget';
+ return $this->selector;
}
/**
@@ -34,13 +34,9 @@
*/
public function assert($browser)
{
-// $list = explode("\n", $browser->value($this->selector));
-
- $browser->waitFor($this->selector())
- ->assertMissing($this->selector)
+ $browser->assertVisible($this->selector())
->assertVisible('@input')
->assertVisible('@add-btn');
-// ->assertListInputValue($list);
}
/**
diff --git a/src/tests/Browser/UsersTest.php b/src/tests/Browser/UsersTest.php
--- a/src/tests/Browser/UsersTest.php
+++ b/src/tests/Browser/UsersTest.php
@@ -142,7 +142,7 @@
->assertValue('div.row:nth-child(4) input[type=text]', 'john@kolab.org')
->assertDisabled('div.row:nth-child(4) input[type=text]')
->assertSeeIn('div.row:nth-child(5) label', 'Email aliases')
- ->assertVisible('div.row:nth-child(5) .listinput-widget')
+ ->assertVisible('div.row:nth-child(5) .list-input')
->with(new ListInput('#aliases'), function (Browser $browser) {
$browser->assertListInputValue(['john.doe@kolab.org'])
->assertValue('@input', '');
@@ -343,7 +343,7 @@
->assertValue('div.row:nth-child(3) input[type=text]', '')
->assertEnabled('div.row:nth-child(3) input[type=text]')
->assertSeeIn('div.row:nth-child(4) label', 'Email aliases')
- ->assertVisible('div.row:nth-child(4) .listinput-widget')
+ ->assertVisible('div.row:nth-child(4) .list-input')
->with(new ListInput('#aliases'), function (Browser $browser) {
$browser->assertListInputValue([])
->assertValue('@input', '');

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 6, 1:58 AM (5 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18775695
Default Alt Text
D1120.1775440694.diff (10 KB)

Event Timeline