diff options
author | John Molakvoæ <skjnldsv@users.noreply.github.com> | 2019-03-10 20:18:14 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-10 20:18:14 +0100 |
commit | 7cefc8d04fe85f5fd39dddeef1842b4d85da4392 (patch) | |
tree | 6eeaf451ce548601180ef8d3287b17e1308f894e | |
parent | 7898d34a2b1240294764f8531d83734e063effbe (diff) | |
parent | 857cdebbeda28c05b8a527c57f79fedf404e8b30 (diff) |
Merge pull request #981 from nextcloud/fix/conflict
Fix/conflict
-rw-r--r-- | css/ContactDetails.scss | 5 | ||||
-rw-r--r-- | css/icons.scss | 18 | ||||
-rw-r--r-- | img/delete.svg | 1 | ||||
-rw-r--r-- | img/download.svg | 1 | ||||
-rw-r--r-- | img/upload.svg | 1 | ||||
-rw-r--r-- | src/components/ContactDetails.vue | 15 | ||||
-rw-r--r-- | src/components/Properties/PropertyGroups.vue | 2 | ||||
-rw-r--r-- | src/services/parseVcf.js | 4 | ||||
-rw-r--r-- | src/services/validate.js | 6 | ||||
-rw-r--r-- | src/store/contacts.js | 26 | ||||
-rw-r--r-- | src/views/Contacts.vue | 6 | ||||
-rw-r--r-- | webpack.common.js | 1 |
12 files changed, 66 insertions, 20 deletions
diff --git a/css/ContactDetails.scss b/css/ContactDetails.scss index e4b8c8bc..85f18a80 100644 --- a/css/ContactDetails.scss +++ b/css/ContactDetails.scss @@ -72,6 +72,11 @@ position: relative; height: 44px; width: 44px; + // ! override default server class + > .icon-more-white { + // using #fffffe to trick the accessibility dark theme icon invert + @include icon-color('more', 'actions', '#fffffe', 1, true); + } } .header-icon { height: 44px; diff --git a/css/icons.scss b/css/icons.scss index 60cb2b32..6192e631 100644 --- a/css/icons.scss +++ b/css/icons.scss @@ -40,17 +40,27 @@ @include icon-color('up', 'contacts', $color-black, 1); } +.icon-up-force-white { + // using #fffffe to trick the accessibility dark theme icon invert + @include icon-color('up', 'contacts', '#fffffe', 1); +} + +.icon-history-force-white { + // using #fffffe to trick the accessibility dark theme icon invert + @include icon-color('history', 'actions', '#fffffe', 1, true); +} + .icon-delete-force-white { // using #fffffe to trick the accessibility dark theme icon invert - @include icon-color('delete', 'contacts', '#fffffe', 1); + @include icon-color('delete', 'actions', '#fffffe', 1, true); } .icon-download-force-white { // using #fffffe to trick the accessibility dark theme icon invert - @include icon-color('download', 'contacts', '#fffffe', 1); + @include icon-color('download', 'actions', '#fffffe', 1, true); } .icon-upload-force-white { // using #fffffe to trick the accessibility dark theme icon invert - @include icon-color('upload', 'contacts', '#fffffe', 1); -}
\ No newline at end of file + @include icon-color('upload', 'actions', '#fffffe', 1, true); +} diff --git a/img/delete.svg b/img/delete.svg deleted file mode 100644 index 53f0b020..00000000 --- a/img/delete.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 16 16" width="16" height="16"><path d="M6.5 1L6 2H3c-.554 0-1 .446-1 1v1h12V3c0-.554-.446-1-1-1h-3l-.5-1zM3 5l.875 9c.06.55.573 1 1.125 1h6c.552 0 1.064-.45 1.125-1L13 5z"/></svg> diff --git a/img/download.svg b/img/download.svg deleted file mode 100644 index dd2389b2..00000000 --- a/img/download.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 16 16" width="16" height="16"><path d="M6 1h4v7h5l-7 7-7-7h5z"/></svg> diff --git a/img/upload.svg b/img/upload.svg deleted file mode 100644 index 92ca7920..00000000 --- a/img/upload.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 16 16" width="16" height="16"><path d="M8 1L2 7h4v4h4V7h4zM2 13v2h12v-2z"/></svg> diff --git a/src/components/ContactDetails.vue b/src/components/ContactDetails.vue index c5f2bfd8..b740e0d5 100644 --- a/src/components/ContactDetails.vue +++ b/src/components/ContactDetails.vue @@ -77,7 +77,7 @@ content: conflict, show: true, trigger: 'manual', - }" class="header-icon header-icon--pulse icon-history-white" + }" class="header-icon header-icon--pulse icon-history-force-white" @click="refreshContact" /> <div class="menu-icon"> <div v-click-outside="closeMenu" class="header-icon icon-more-white" @click="toggleMenu" /> @@ -127,6 +127,7 @@ import debounce from 'debounce' import PQueue from 'p-queue' import rfcProps from 'Models/rfcProps' +import validate from 'Services/validate' import ContactProperty from './ContactDetails/ContactDetailsProperty' import AddNewProp from './ContactDetails/ContactDetailsAddNewProp' @@ -162,6 +163,8 @@ export default { data() { return { + // if true, the local contact have been fixed and requires a push + fixed: false, /** * Local off-store clone of the selected contact for edition * because we can't edit contacts data outside the store. @@ -368,6 +371,7 @@ export default { * Send the local clone of contact to the store */ async updateContact() { + this.fixed = false this.loadingUpdate = true await this.$store.dispatch('updateContact', this.localContact) this.loadingUpdate = false @@ -421,6 +425,9 @@ export default { Object.create(Object.getPrototypeOf(contact)), contact ) + + this.fixed = validate(localContact) + this.localContact = localContact this.loadingData = false } catch (error) { @@ -438,10 +445,14 @@ export default { } else { // create empty contact and copy inner data // wait for an update to really push the contact on the server! - this.localContact = Object.assign( + let localContact = Object.assign( Object.create(Object.getPrototypeOf(contact)), contact ) + + this.fixed = validate(localContact) + + this.localContact = localContact this.loadingData = false } diff --git a/src/components/Properties/PropertyGroups.vue b/src/components/Properties/PropertyGroups.vue index 0ac44d0b..4cdf296b 100644 --- a/src/components/Properties/PropertyGroups.vue +++ b/src/components/Properties/PropertyGroups.vue @@ -50,7 +50,7 @@ <script> import debounce from 'debounce' -import Contact from '../../models/contact' +import Contact from 'Models/contact' export default { name: 'PropertyGroups', diff --git a/src/services/parseVcf.js b/src/services/parseVcf.js index 184c8e76..f8fc0f0c 100644 --- a/src/services/parseVcf.js +++ b/src/services/parseVcf.js @@ -20,8 +20,8 @@ * */ -import Contact from '../models/contact' -import Store from '../store/index' +import Contact from 'Models/contact' +import Store from 'Store/index' export default function parseVcf(data = '', addressbook) { let regexp = /BEGIN:VCARD[\s\S]*?END:VCARD/mgi diff --git a/src/services/validate.js b/src/services/validate.js index c80542f9..e4245c4b 100644 --- a/src/services/validate.js +++ b/src/services/validate.js @@ -20,10 +20,11 @@ * */ -import Contact from '../models/contact' +import Contact from 'Models/contact' import checks from './checks/' export default function(contact) { + let result = false if (contact instanceof Contact) { // Going through every checks @@ -37,6 +38,7 @@ export default function(contact) { console.warn('The following contact needed a correction that failed:', check.name, contact) } else { // SUCCESS 💪 + result = true console.info('The following contact has been repaired:', check.name, contact) } } @@ -44,7 +46,7 @@ export default function(contact) { console.error('Error during the check:', check.name, contact, error) } }) - + return result } else { throw new Error('Invalid contact provided') } diff --git a/src/store/contacts.js b/src/store/contacts.js index e520d160..4b98291f 100644 --- a/src/store/contacts.js +++ b/src/store/contacts.js @@ -22,8 +22,8 @@ import Vue from 'vue' import ICAL from 'ical.js' -import Contact from '../models/contact' -import validate from '../services/validate' +import Contact from 'Models/contact' +import validate from 'Services/validate' const state = { // Using objects for performance @@ -232,6 +232,22 @@ const mutations = { */ setOrder(state, orderKey = 'displayName') { state.orderKey = orderKey + }, + + /** + * Set a contact as `in conflict` with the server data + * + * @param {Object} state the store data + * @param {Object} data destructuring object + * @param {Contact} data.contact the contact to update + * @param {String} data.etag the etag to set + */ + setContactAsConflict(state, { contact, etag }) { + if (state.contacts[contact.key] && contact instanceof Contact) { + state.contacts[contact.key].conflict = etag + } else { + console.error('Error while handling the following contact', contact) + } } } @@ -314,12 +330,14 @@ const actions = { // all clear, let's update the store context.commit('updateContact', contact) }) - .catch((error) => { + .catch(error => { + console.info(error) // wrong etag, we most likely have a conflict if (error && error.status === 412) { // saving the new etag so that the user can manually // trigger a fetchCompleteData without any further errors - contact.conflict = error.xhr.getResponseHeader('etag') + context.commit('setContactAsConflict', { contact, etag: error.xhr.getResponseHeader('etag') }) + console.error('This contact is outdated, the server refused it', contact) } }) } else { diff --git a/src/views/Contacts.vue b/src/views/Contacts.vue index d785d748..5e6d31de 100644 --- a/src/views/Contacts.vue +++ b/src/views/Contacts.vue @@ -24,7 +24,7 @@ <template> <app-content app-name="contacts" :class="{'icon-loading': loading}"> <!-- new-contact-button + navigation + settings --> - <template slot="navigation"> + <app-navigation slot="navigation"> <!-- new-contact-button --> <app-navigation-new v-if="!loading" button-id="new-contact-button" :text="t('contacts','New contact')" button-class="icon-add" :disabled="!defaultAddressbook" @click="newContact" /> @@ -38,7 +38,7 @@ <app-navigation-settings v-if="!loading"> <settings-section /> </app-navigation-settings> - </template> + </app-navigation> <template slot="content"> <!-- go back to list when in details mode --> @@ -64,6 +64,7 @@ <script> import { AppContent, + AppNavigation, AppNavigationItem, AppNavigationNew, AppNavigationSettings @@ -87,6 +88,7 @@ export default { components: { AppContent, + AppNavigation, AppNavigationItem, AppNavigationNew, AppNavigationSettings, diff --git a/webpack.common.js b/webpack.common.js index 5320f430..80c655a4 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -52,6 +52,7 @@ module.exports = { Mixins: path.resolve(__dirname, 'src/mixins/'), Models: path.resolve(__dirname, 'src/models/'), Services: path.resolve(__dirname, 'src/services/'), + Store: path.resolve(__dirname, 'src/store/'), Views: path.resolve(__dirname, 'src/views/') }, extensions: ['*', '.js', '.vue', '.json'] |