summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@users.noreply.github.com>2018-11-09 19:18:47 +0100
committerGitHub <noreply@github.com>2018-11-09 19:18:47 +0100
commit1bfdf08c66254857178606006e8e2611a831f0f0 (patch)
treef2f6d227624ded0e1787a80dceb68f82d46a2130
parent38ea18f362d5c506582cfa715f30789fb85beae3 (diff)
parent5729951b251f2ffd4471ed0c92c77fbfe8d4c61a (diff)
Merge pull request #704 from nextcloud/disabled-ab-should-not-be-suggested
Disabled ab should not be suggested
-rw-r--r--.travis.yml1
-rw-r--r--css/Properties/Properties.scss14
-rw-r--r--css/Settings/SettingsAddressbook.scss1
-rw-r--r--css/Settings/SettingsAddressbookSharee.scss5
-rw-r--r--css/Settings/SettingsAddressbookShares.scss3
-rw-r--r--css/SettingsSection.scss41
-rw-r--r--css/icons.scss4
-rw-r--r--img/address-book.svg2
-rw-r--r--src/components/ContactDetails.vue4
-rw-r--r--src/components/Properties/PropertySelect.vue8
-rw-r--r--src/components/Settings/SettingsAddressbook.vue30
-rw-r--r--src/components/Settings/SettingsImportContacts.vue50
-rw-r--r--src/components/Settings/SettingsSortContacts.vue21
-rw-r--r--src/main.js16
-rw-r--r--webpack.common.js6
15 files changed, 122 insertions, 84 deletions
diff --git a/.travis.yml b/.travis.yml
index 86d38e93..25b6e682 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,3 +8,4 @@ script:
- npm run build
- npm run lint
- npm run stylelint
+- npm run test
diff --git a/css/Properties/Properties.scss b/css/Properties/Properties.scss
index 8ca4bf90..5add862b 100644
--- a/css/Properties/Properties.scss
+++ b/css/Properties/Properties.scss
@@ -71,7 +71,7 @@
// property label or multiselect within row
&__label,
- &__label.multiselect {
+ &__label.multiselect.multiselect-vue {
margin: $grid-input-margin;
margin: $grid-input-margin 5px $grid-input-margin 0;
height: $grid-input-height-with-margin;
@@ -81,6 +81,10 @@
user-select: none;
background-size: 16px;
+ .multiselect__tags {
+ border-color: transparent;
+ }
+
&,
.multiselect__input::placeholder {
text-align: right;
@@ -93,10 +97,15 @@
overflow-x: hidden;
}
+ // mouse feedback
&.multiselect {
&:hover,
- &:focus {
+ &:focus,
+ &:active {
opacity: 1;
+ .multiselect__tags {
+ border-color: var(--color-border-dark);
+ }
}
}
}
@@ -105,7 +114,6 @@
.multiselect__tags {
border: none;
.multiselect__single {
- @include icon-color('triangle-s', 'actions', $color-black, 1, true);
background-repeat: no-repeat;
background-position: center right 4px;
padding-right: 24px;
diff --git a/css/Settings/SettingsAddressbook.scss b/css/Settings/SettingsAddressbook.scss
index 92d6fc20..680a7c7d 100644
--- a/css/Settings/SettingsAddressbook.scss
+++ b/css/Settings/SettingsAddressbook.scss
@@ -23,6 +23,7 @@
.addressbook {
display: flex;
+ flex-wrap: wrap;
align-items: center;
white-space: nowrap;
text-overflow: ellipsis;
diff --git a/css/Settings/SettingsAddressbookSharee.scss b/css/Settings/SettingsAddressbookSharee.scss
index c9777c52..82fafebb 100644
--- a/css/Settings/SettingsAddressbookSharee.scss
+++ b/css/Settings/SettingsAddressbookSharee.scss
@@ -57,12 +57,15 @@
width: 16px;
height: 16px;
display: inline-block;
+ margin-bottom: 2px;
}
.icon-delete {
display: inline-block;
- width: 24px;
+ width: 20px;
height: 20px;
opacity: 0.4;
+ margin-bottom: 2px;
+ margin-left: 4px;
}
} \ No newline at end of file
diff --git a/css/Settings/SettingsAddressbookShares.scss b/css/Settings/SettingsAddressbookShares.scss
index 9a311bb6..87cf2f9c 100644
--- a/css/Settings/SettingsAddressbookShares.scss
+++ b/css/Settings/SettingsAddressbookShares.scss
@@ -41,8 +41,9 @@
width: 14px;
}
- .multiselect {
+ .multiselect.multiselect-vue {
width: inherit;
+ margin: 0;
.multiselect__tags:focus-within,
.multiselect__tags:hover {
border-color: var(--color-primary-element);
diff --git a/css/SettingsSection.scss b/css/SettingsSection.scss
index c4989001..561036df 100644
--- a/css/SettingsSection.scss
+++ b/css/SettingsSection.scss
@@ -26,27 +26,29 @@
.settings-section {
display: flex;
align-items: center;
+ margin-top: 5px;
}
}
#new-addressbook-form {
display: flex;
+ input {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
}
// Sort Contacts
.sort-contacts {
.multiselect.multiselect-vue {
- width: 120px;
- margin-left: 5px;
- }
- input#sort-by, .multiselect__single {
- padding: 6px 12px;
- min-height: 34px;
- text-align: center;
- background: url(/core/css/../img/actions/triangle-s.svg) no-repeat right 4px center;
- background-color: inherit;
- outline: 0;
- padding-right: 24px !important;
+ width: 100%;
+ margin: 0;
+ .multiselect__single {
+ padding-right: 24px !important;
+ @include icon-color('triangle-s', 'actions', $color-black, 1, true);
+ background-repeat: no-repeat;
+ background-position: right 4px center;
+ }
}
}
@@ -54,22 +56,21 @@
.import-contact {
display: flex;
flex-direction: column;
- .multiselect-label {
+ &__multiselect-label {
width: 100%;
- padding: 6px 12px 6px 34px;
+ padding: 6px 12px;
+ padding-left: 34px;
margin: 0;
border-radius: var(--border-radius) var(--border-radius) 0 0;
- background: url(/core/css/../img/actions/upload.svg) no-repeat left 9px center;
- background-color: #f7f7f7;
+ background-position: left 9px center;
z-index: 2;
+ &--no-select {
+ border-radius: var(--border-radius);
+ }
}
- .multiselect-vue {
+ &__multiselect.multiselect.multiselect-vue {
width: 100%;
margin: 0;
- }
- .multiselect-vue .multiselect__tags {
- border: 1px solid var(--color-border-dark);
- border-radius: 0 0 var(--border-radius) var(--border-radius);
margin-top: -1px;
}
}
diff --git a/css/icons.scss b/css/icons.scss
index f688ac51..e5b18450 100644
--- a/css/icons.scss
+++ b/css/icons.scss
@@ -22,4 +22,8 @@
.icon-social {
@include icon-color('social', 'contacts', $color-black, 1);
+}
+
+.icon-address-book {
+ @include icon-color('address-book', 'contacts', $color-black, 1);
} \ No newline at end of file
diff --git a/img/address-book.svg b/img/address-book.svg
new file mode 100644
index 00000000..6be6e4ab
--- /dev/null
+++ b/img/address-book.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1703 478q40 57 18 129l-275 906q-19 64-76.5 107.5t-122.5 43.5h-923q-77 0-148.5-53.5t-99.5-131.5q-24-67-2-127 0-4 3-27t4-37q1-8-3-21.5t-3-19.5q2-11 8-21t16.5-23.5 16.5-23.5q23-38 45-91.5t30-91.5q3-10 .5-30t-.5-28q3-11 17-28t17-23q21-36 42-92t25-90q1-9-2.5-32t.5-28q4-13 22-30.5t22-22.5q19-26 42.5-84.5t27.5-96.5q1-8-3-25.5t-2-26.5q2-8 9-18t18-23 17-21q8-12 16.5-30.5t15-35 16-36 19.5-32 26.5-23.5 36-11.5 47.5 5.5l-1 3q38-9 51-9h761q74 0 114 56t18 130l-274 906q-36 119-71.5 153.5t-128.5 34.5h-869q-27 0-38 15-11 16-1 43 24 70 144 70h923q29 0 56-15.5t35-41.5l300-987q7-22 5-57 38 15 59 43zm-1064 2q-4 13 2 22.5t20 9.5h608q13 0 25.5-9.5t16.5-22.5l21-64q4-13-2-22.5t-20-9.5h-608q-13 0-25.5 9.5t-16.5 22.5zm-83 256q-4 13 2 22.5t20 9.5h608q13 0 25.5-9.5t16.5-22.5l21-64q4-13-2-22.5t-20-9.5h-608q-13 0-25.5 9.5t-16.5 22.5z"/></svg> \ No newline at end of file
diff --git a/src/components/ContactDetails.vue b/src/components/ContactDetails.vue
index 3517b24e..206aa749 100644
--- a/src/components/ContactDetails.vue
+++ b/src/components/ContactDetails.vue
@@ -237,7 +237,7 @@ export default {
addressbookModel() {
return {
readableName: t('contacts', 'Addressbook'),
- icon: 'icon-addressbook',
+ icon: 'icon-address-book',
options: this.addressbooksOptions
}
},
@@ -264,7 +264,7 @@ export default {
*/
addressbooksOptions() {
return this.addressbooks
- .filter(addressbook => !addressbook.readOnly)
+ .filter(addressbook => !addressbook.readOnly && addressbook.enabled)
.map(addressbook => {
return {
id: addressbook.id,
diff --git a/src/components/Properties/PropertySelect.vue b/src/components/Properties/PropertySelect.vue
index f7b7b0bb..92508124 100644
--- a/src/components/Properties/PropertySelect.vue
+++ b/src/components/Properties/PropertySelect.vue
@@ -38,8 +38,8 @@
<button :title="t('contacts', 'Delete')" class="property__delete icon-delete" @click="deleteProperty" />
<multiselect v-model="matchedOptions" :options="propModel.options" :placeholder="t('contacts', 'Select option')"
- class="property__value" track-by="id" label="name"
- @input="updateValue" />
+ :disabled="isSingleOption" class="multiselect-vue property__value" track-by="id"
+ label="name" @input="updateValue" />
</div>
</div>
</template>
@@ -95,6 +95,10 @@ export default {
// length is one & add one space at the end
return hasTitle + 1 + isLast
},
+ // is there only one option available
+ isSingleOption() {
+ return this.propModel.options.length <= 1
+ },
// matching value to the options we provide
matchedOptions: {
diff --git a/src/components/Settings/SettingsAddressbook.vue b/src/components/Settings/SettingsAddressbook.vue
index aaf9cd4c..9a580cc9 100644
--- a/src/components/Settings/SettingsAddressbook.vue
+++ b/src/components/Settings/SettingsAddressbook.vue
@@ -21,24 +21,22 @@
-
-->
<template>
- <div>
- <li :class="{'addressbook--disabled': !addressbook.enabled}" class="addressbook">
- <!-- addressbook name -->
- <span class="addressbook__name">{{ addressbook.displayName }}</span>
- <!-- sharing button -->
- <a href="#" class="addressbook__share icon-shared"
- @click="toggleShare" />
- <!-- popovermenu -->
- <a v-click-outside="closeMenu" href="#" class="addressbook__menu">
- <div class="icon-more" @click="toggleMenu" />
- <div :class="{open: menuOpen}" class="popovermenu">
- <popover-menu :menu="menu" />
- </div>
- </a>
- </li>
+ <li :class="{'addressbook--disabled': !addressbook.enabled}" class="addressbook">
+ <!-- addressbook name -->
+ <span class="addressbook__name">{{ addressbook.displayName }}</span>
+ <!-- sharing button -->
+ <a href="#" class="addressbook__share icon-shared"
+ @click="toggleShare" />
+ <!-- popovermenu -->
+ <a v-click-outside="closeMenu" href="#" class="addressbook__menu">
+ <div class="icon-more" @click="toggleMenu" />
+ <div :class="{open: menuOpen}" class="popovermenu">
+ <popover-menu :menu="menu" />
+ </div>
+ </a>
<!-- sharing input -->
<share-address-book v-if="shareOpen" :addressbook="addressbook" />
- </div>
+ </li>
</template>
<script>
diff --git a/src/components/Settings/SettingsImportContacts.vue b/src/components/Settings/SettingsImportContacts.vue
index 725637e0..e52b9f03 100644
--- a/src/components/Settings/SettingsImportContacts.vue
+++ b/src/components/Settings/SettingsImportContacts.vue
@@ -22,17 +22,24 @@
<template>
<div class="import-contact">
- <input id="contact-import" type="file" class="hidden-visually"
- @change="processFile">
- <label id="upload" for="contact-import" class="button multiselect-label icon-upload no-select">
- {{ t('contacts', 'Import into') }}
- </label>
- <multiselect
- v-model="selectedAddressbook"
- :options="options"
- :disabled="isSingleAddressbook"
- :placeholder="t('contacts', 'Contacts')"
- label="displayName" />
+ <template v-if="!isNoAddressbookAvailable">
+ <input id="contact-import" type="file" class="hidden-visually"
+ @change="processFile">
+ <label id="upload" for="contact-import" class="button import-contact__multiselect-label icon-upload">
+ {{ t('contacts', 'Import into') }}
+ </label>
+ <multiselect
+ v-model="selectedAddressbook"
+ :options="options"
+ :disabled="isSingleAddressbook"
+ :placeholder="t('contacts', 'Contacts')"
+ label="displayName"
+ class="multiselect-vue import-contact__multiselect" />
+ </template>
+ <button v-else id="upload" for="contact-import"
+ class="button import-contact__multiselect-label import-contact__multiselect--no-select icon-error">
+ {{ t('contacts', 'Importing is disabled because there are no address books available') }}
+ </button>
</div>
</template>
@@ -51,12 +58,14 @@ export default {
return this.$store.getters.getAddressbooks
},
options() {
- return this.addressbooks.map(addressbook => {
- return {
- id: addressbook.id,
- displayName: addressbook.displayName
- }
- })
+ return this.addressbooks
+ .filter(addressbook => !addressbook.readOnly && addressbook.enabled)
+ .map(addressbook => {
+ return {
+ id: addressbook.id,
+ displayName: addressbook.displayName
+ }
+ })
},
importState() {
return this.$store.getters.getImportState
@@ -73,9 +82,12 @@ export default {
this.importDestination = value
}
},
- // disable multiselect when there is at most one address book
+ // disable multiselect when there is only one address book
isSingleAddressbook() {
- return this.addressbooks.length <= 1
+ return this.options.length === 1
+ },
+ isNoAddressbookAvailable() {
+ return this.options.length < 1
}
},
methods: {
diff --git a/src/components/Settings/SettingsSortContacts.vue b/src/components/Settings/SettingsSortContacts.vue
index 6e13f575..d6cb83c5 100644
--- a/src/components/Settings/SettingsSortContacts.vue
+++ b/src/components/Settings/SettingsSortContacts.vue
@@ -22,13 +22,13 @@
<template>
<div class="sort-contacts">
- <label for="sort-by">{{ t('contacts', 'Sort by:') }}</label>
<multiselect
id="sort-by"
- :placeholder="orderKey"
+ :value="orderKeyOption"
:searchable="false"
:allow-empty="false"
:options="options"
+ :custom-label="formatSortByLabel"
track-by="key"
label="label"
@input="sortContacts" />
@@ -40,15 +40,6 @@
export default {
name: 'SettingsSortContacts',
- props: {
- addressbook: {
- type: Object,
- default() {
- return {}
- }
- }
- },
-
computed: {
/* Order Keys */
options() {
@@ -69,7 +60,10 @@ export default {
},
/* Current order Key */
orderKey() {
- return t('contacts', this.options.filter(f => f.key === this.$store.getters.getOrderKey)[0].label)
+ return this.$store.getters.getOrderKey
+ },
+ orderKeyOption() {
+ return this.options.filter(option => option.key === this.orderKey)[0]
}
},
methods: {
@@ -78,6 +72,9 @@ export default {
this.$store.commit('setOrder', key)
this.$store.commit('sortContacts')
localStorage.setItem('orderKey', key)
+ },
+ formatSortByLabel(option) {
+ return t('contacts', 'Sort by {sorting}', { sorting: option.label })
}
}
}
diff --git a/src/main.js b/src/main.js
index 5d02fcb9..dd27bd7d 100644
--- a/src/main.js
+++ b/src/main.js
@@ -33,14 +33,6 @@ import ClickOutside from 'vue-click-outside'
import Tooltip from 'v-tooltip'
import VueClipboard from 'vue-clipboard2'
-Vue.component('AppNavigation', AppNavigation)
-Vue.component('DatetimePicker', DatetimePicker)
-Vue.component('Multiselect', Multiselect)
-Vue.component('PopoverMenu', PopoverMenu)
-Vue.directive('ClickOutside', ClickOutside)
-Vue.directive('Tooltip', Tooltip)
-Vue.use(VueClipboard)
-
// CSP config for webpack dynamic chunk loading
// eslint-disable-next-line
__webpack_nonce__ = btoa(OC.requestToken)
@@ -52,6 +44,14 @@ __webpack_nonce__ = btoa(OC.requestToken)
// eslint-disable-next-line
__webpack_public_path__ = OC.linkTo('contacts', 'js/')
+Vue.component('AppNavigation', AppNavigation)
+Vue.component('DatetimePicker', DatetimePicker)
+Vue.component('Multiselect', Multiselect)
+Vue.component('PopoverMenu', PopoverMenu)
+Vue.directive('ClickOutside', ClickOutside)
+Vue.directive('Tooltip', Tooltip)
+Vue.use(VueClipboard)
+
sync(store, router)
Vue.prototype.t = t
diff --git a/webpack.common.js b/webpack.common.js
index 409625f8..5e2c4b31 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -11,6 +11,12 @@ module.exports = {
filename: 'contacts.js',
chunkFilename: 'chunks/[name].js'
},
+ optimization: {
+ splitChunks: {
+ automaticNameDelimiter: '-',
+ chunks: 'all'
+ }
+ },
module: {
rules: [
{