summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2018-09-11 14:21:43 +0200
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2018-09-11 14:21:43 +0200
commite05430b93cc823a68c17274ce177b3dee5c031a3 (patch)
tree8e218ce13e19867612988fdd0ae58fc2c8ecd50a
parentc57de33393faf2073d2a614b6da9fb088927859f (diff)
Migrate components to nextcloud repo
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
-rw-r--r--Makefile7
-rw-r--r--package-lock.json53
-rw-r--r--package.json3
-rw-r--r--src/components/ContactDetails.vue2
-rw-r--r--src/components/Settings/SettingsAddressbook.vue17
-rw-r--r--src/components/core/appNavigation.vue96
-rw-r--r--src/components/core/appNavigation/navigationItem.vue162
-rw-r--r--src/components/core/popoverMenu.vue51
-rw-r--r--src/components/core/popoverMenu/popoverItem.vue87
-rw-r--r--src/views/Contacts.vue21
10 files changed, 63 insertions, 436 deletions
diff --git a/Makefile b/Makefile
index 274f50a7..d8c4f33a 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,13 @@ lint:
lint-fix:
npm run lint:fix
+# Style linting
+stylelint:
+ npm run stylelint
+
+stylelint-fix:
+ npm run stylelint:fix
+
# Cleaning
clean:
rm -f js/contacts.js
diff --git a/package-lock.json b/package-lock.json
index 5d263993..662b6133 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6257,6 +6257,11 @@
"bser": "^2.0.0"
}
},
+ "fecha": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
+ "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
+ },
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
@@ -6511,14 +6516,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6533,20 +6536,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -6663,8 +6663,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -6676,7 +6675,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -6691,7 +6689,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -6699,14 +6696,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -6725,7 +6720,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -6806,8 +6800,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -6819,7 +6812,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -6941,7 +6933,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -10672,6 +10663,18 @@
"integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==",
"dev": true
},
+ "nextcloud-vue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/nextcloud-vue/-/nextcloud-vue-0.1.0.tgz",
+ "integrity": "sha512-gBRQ7TP7vtH9SfhpzdLSMaZPVpwBLK9E0py6D1192XQcqUr6m2c4wefXJI9NchRPHOv5oZnDVFrRniuU4RODgw==",
+ "requires": {
+ "babel-polyfill": "^6.26.0",
+ "v-tooltip": "^2.0.0-rc.33",
+ "vue": "^2.5.16",
+ "vue-click-outside": "^1.0.7",
+ "vue2-datepicker": "^2.4.1"
+ }
+ },
"nice-try": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz",
@@ -15385,6 +15388,14 @@
"integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==",
"dev": true
},
+ "vue2-datepicker": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/vue2-datepicker/-/vue2-datepicker-2.4.1.tgz",
+ "integrity": "sha512-+m1JOIY0Dbsbkiz3KMsw5O1Ai/aX1AEdRGKar/VaudAgS4JV0ImF42JGDFbNf5+HQ1cuq6NDnUkSQeyezANUWw==",
+ "requires": {
+ "fecha": "^2.3.3"
+ }
+ },
"vuex": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.0.1.tgz",
diff --git a/package.json b/package.json
index f5f48e1b..2c28d152 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,8 @@
"build": "webpack --progress --hide-modules --config webpack.prod.js",
"lint": "eslint --ext .js,.vue src tests",
"lint:fix": "eslint --ext .js,.vue src tests --fix",
+ "stylelint": "stylelint src",
+ "stylelint:fix": "stylelint src --fix",
"test": "jest",
"test:coverage": "jest --coverage"
},
@@ -20,6 +22,7 @@
"cdav-library": "github:nextcloud/cdav-library#develop",
"debounce": "^1.2.0",
"ical.js": "^1.2.2",
+ "nextcloud-vue": "^0.1.0",
"uuid": "^3.3.2",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.5.17",
diff --git a/src/components/ContactDetails.vue b/src/components/ContactDetails.vue
index 0b506716..d69e2152 100644
--- a/src/components/ContactDetails.vue
+++ b/src/components/ContactDetails.vue
@@ -99,6 +99,7 @@
</template>
<script>
+import { PopoverMenu } from 'nextcloud-vue'
import ClickOutside from 'vue-click-outside'
import Vue from 'vue'
import VTooltip from 'v-tooltip'
@@ -107,7 +108,6 @@ import debounce from 'debounce'
import Contact from '../models/contact'
import rfcProps from '../models/rfcProps.js'
-import PopoverMenu from './core/popoverMenu'
import ContactProperty from './ContactDetails/ContactDetailsProperty'
import AddNewProp from './ContactDetails/ContactDetailsAddNewProp'
import PropertySelect from './Properties/PropertySelect'
diff --git a/src/components/Settings/SettingsAddressbook.vue b/src/components/Settings/SettingsAddressbook.vue
index 80cb533a..dabe0bc2 100644
--- a/src/components/Settings/SettingsAddressbook.vue
+++ b/src/components/Settings/SettingsAddressbook.vue
@@ -43,23 +43,24 @@
<script>
import Vue from 'vue'
-import popoverMenu from '../core/popoverMenu'
-import shareAddressBook from './SettingsAddressbookShare'
-import renameAddressBookField from './SettingsRenameAddressbookField'
-import clickOutside from 'vue-click-outside'
+import { PopoverMenu } from 'nextcloud-vue'
+import ClickOutside from 'vue-click-outside'
import VueClipboard from 'vue-clipboard2'
+import ShareAddressBook from './SettingsAddressbookShare'
+import RenameAddressBookField from './SettingsRenameAddressbookField'
+
Vue.use(VueClipboard)
export default {
name: 'SettingsAddressbook',
components: {
- popoverMenu,
- shareAddressBook,
- renameAddressBookField
+ PopoverMenu,
+ ShareAddressBook,
+ RenameAddressBookField
},
directives: {
- clickOutside
+ ClickOutside
},
props: {
addressbook: {
diff --git a/src/components/core/appNavigation.vue b/src/components/core/appNavigation.vue
deleted file mode 100644
index 8793e9eb..00000000
--- a/src/components/core/appNavigation.vue
+++ /dev/null
@@ -1,96 +0,0 @@
-<!--
- - @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @author John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero General Public License as
- - published by the Free Software Foundation, either version 3 of the
- - License, or (at your option) any later version.
- -
- - This program is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
- -->
-
-<template>
- <div id="app-navigation" :class="{'icon-loading': menu.loading}">
- <div v-if="menu.new" class="app-navigation-new">
- <button :id="menu.new.id" :class="menu.new.icon" type="button"
- @click="menu.new.action">{{ menu.new.text }}</button>
- </div>
- <ul :id="menu.id">
- <navigation-item v-for="item in menu.items" :item="item" :key="item.key" />
- </ul>
- <div v-click-outside="closeMenu" v-if="!!$slots['settings-content']" id="app-settings"
- :class="{open: opened}">
- <div id="app-settings-header">
- <button class="settings-button"
- data-apps-slide-toggle="#app-settings-content"
- @click="toggleMenu"
- >{{ t('contacts', 'Settings') }}</button>
- </div>
- <div id="app-settings-content">
- <slot name="settings-content" />
- </div>
- </div>
- </div>
-</template>
-
-<script>
-import navigationItem from './appNavigation/navigationItem'
-import clickOutside from 'vue-click-outside'
-
-export default {
- name: 'AppNavigation',
- components: {
- navigationItem,
- clickOutside
- },
- directives: {
- clickOutside
- },
- props: {
- menu: {
- type: Object,
- required: true,
- default: () => {
- return {
- new: {
- id: 'new-item',
- action: () => alert('Success!'),
- icon: 'icon-add',
- text: 'New item'
- },
- menu: {
- id: 'navigation',
- items: [
-
- ]
- }
- }
- }
- }
- },
- data() {
- return {
- opened: false
- }
- },
- methods: {
- toggleMenu() {
- this.opened = !this.opened
- },
- closeMenu() {
- this.opened = false
- }
- }
-}
-</script>
diff --git a/src/components/core/appNavigation/navigationItem.vue b/src/components/core/appNavigation/navigationItem.vue
deleted file mode 100644
index 925ed4c2..00000000
--- a/src/components/core/appNavigation/navigationItem.vue
+++ /dev/null
@@ -1,162 +0,0 @@
-<!--
- - @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @author John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero General Public License as
- - published by the Free Software Foundation, either version 3 of the
- - License, or (at your option) any later version.
- -
- - This program is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
- -->
-<template>
-
- <!-- Is this a caption ? -->
- <li v-if="item.caption" class="app-navigation-caption">{{ item.text }}</li>
-
- <!-- Navigation item -->
- <nav-element v-else :id="item.id" v-bind="navElement(item)"
- :class="[{'icon-loading-small': item.loading, 'open': item.opened, 'collapsible': item.collapsible&&item.children&&item.children.length>0 }, item.classes]">
-
- <!-- Bullet -->
- <div v-if="item.bullet" :style="{ backgroundColor: item.bullet }" class="app-navigation-entry-bullet" />
-
- <!-- Main link -->
- <a :href="(item.href) ? item.href : '#' " :class="item.icon" @click="toggleCollapse">
- <img v-if="item.iconUrl" :alt="item.text" :src="item.iconUrl">
- {{ item.text }}
- </a>
-
- <!-- Popover, counter and button(s) -->
- <div v-if="item.utils" class="app-navigation-entry-utils">
- <ul>
- <!-- counter -->
- <li v-if="Number.isInteger(item.utils.counter)"
- class="app-navigation-entry-utils-counter">{{ item.utils.counter }}</li>
-
- <!-- first action if only one action and counter -->
- <li v-if="item.utils.actions && item.utils.actions.length === 1 && Number.isInteger(item.utils.counter)"
- class="app-navigation-entry-utils-menu-button">
- <button :class="item.utils.actions[0].icon" :title="item.utils.actions[0].text" @click="item.utils.actions[0].action" />
- </li>
-
- <!-- second action only two actions and no counter -->
- <li v-for="action in item.utils.actions"
- v-else-if="item.utils.actions && item.utils.actions.length === 2 && !Number.isInteger(item.utils.counter)" :key="action.action"
- class="app-navigation-entry-utils-menu-button">
- <button :class="action.icon" :title="action.text" @click="action.action" />
- </li>
-
- <!-- menu if only at least one action and counter OR two actions and no counter-->
- <li v-else-if="item.utils.actions && item.utils.actions.length > 1 && (Number.isInteger(item.utils.counter) || item.utils.actions.length > 2)"
- class="app-navigation-entry-utils-menu-button">
- <button v-click-outside="hideMenu" @click="showMenu" />
- </li>
- </ul>
- </div>
-
- <!-- if more than 2 actions or more than 1 actions with counter -->
- <div v-if="item.utils && item.utils.actions && item.utils.actions.length > 1 && (Number.isInteger(item.utils.counter) || item.utils.actions.length > 2)"
- :class="{ 'open': openedMenu }" class="app-navigation-entry-menu">
- <popover-menu :menu="item.utils.actions" />
- </div>
-
- <!-- undo entry -->
- <div v-if="item.undo" class="app-navigation-entry-deleted">
- <div class="app-navigation-entry-deleted-description">{{ item.undo.text }}</div>
- <button :title="t('settings', 'Undo')" class="app-navigation-entry-deleted-button icon-history" />
- </div>
-
- <!-- edit entry -->
- <div v-if="item.edit" class="app-navigation-entry-edit">
- <form>
- <input v-model="item.text" type="text">
- <input type="submit" value="" class="icon-confirm">
- <input type="submit" value="" class="icon-close"
- @click.stop.prevent="cancelEdit">
- </form>
- </div>
-
- <!-- if the item has children, inject the component with proper data -->
- <ul v-if="item.children">
- <navigation-item v-for="(item, key) in item.children" :item="item" :key="key" />
- </ul>
- </nav-element>
-</template>
-
-<script>
-import popoverMenu from '../popoverMenu'
-import ClickOutside from 'vue-click-outside'
-import Vue from 'vue'
-
-export default {
- name: 'NavigationItem',
- components: {
- popoverMenu
- },
- directives: {
- ClickOutside
- },
- props: {
- item: {
- type: Object,
- required: true
- }
- },
- data() {
- return {
- openedMenu: false
- }
- },
- mounted() {
- // prevent click outside event with popupItem.
- this.popupItem = this.$el
- },
- methods: {
- showMenu() {
- this.openedMenu = true
- },
- hideMenu() {
- this.openedMenu = false
- },
- toggleCollapse() {
- // if item.opened isn't set, Vue won't trigger view updates https://vuejs.org/v2/api/#Vue-set
- // ternary is here to detect the undefined state of item.opened
- Vue.set(this.item, 'opened', this.item.opened ? !this.item.opened : true)
- },
- cancelEdit() {
- // remove the editing class
- if (Array.isArray(this.item.classes)) {
- this.item.classes = this.item.classes.filter(
- item => item !== 'editing'
- )
- }
- },
- // This is used to decide which outter element type to use
- // li or router-link
- navElement(item) {
- if (item.href) {
- return {
- is: 'li'
- }
- }
- return {
- is: 'router-link',
- tag: 'li',
- to: item.router,
- exact: true
- }
- }
- }
-}
-</script>
diff --git a/src/components/core/popoverMenu.vue b/src/components/core/popoverMenu.vue
deleted file mode 100644
index 6c1a0541..00000000
--- a/src/components/core/popoverMenu.vue
+++ /dev/null
@@ -1,51 +0,0 @@
-<!--
- - @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @author John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero General Public License as
- - published by the Free Software Foundation, either version 3 of the
- - License, or (at your option) any later version.
- -
- - This program is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
- -->
-
-<template>
- <ul>
- <popover-item v-for="(item, key) in menu" :item="item" :key="key" />
- </ul>
-</template>
-
-<script>
-import popoverItem from './popoverMenu/popoverItem'
-
-export default {
- name: 'PopoverMenu',
- components: {
- popoverItem
- },
- props: {
- menu: {
- type: Array,
- default: () => {
- return [{
- href: 'https://nextcloud.com',
- icon: 'icon-links',
- text: 'Nextcloud'
- }]
- },
- required: true
- }
- }
-}
-</script>
diff --git a/src/components/core/popoverMenu/popoverItem.vue b/src/components/core/popoverMenu/popoverItem.vue
deleted file mode 100644
index f027404c..00000000
--- a/src/components/core/popoverMenu/popoverItem.vue
+++ /dev/null
@@ -1,87 +0,0 @@
-<!--
- - @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @author John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero General Public License as
- - published by the Free Software Foundation, either version 3 of the
- - License, or (at your option) any later version.
- -
- - This program is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
- -->
-
-<template>
- <li>
- <!-- If item.href is set, a link will be directly used -->
- <a v-if="item.href" :href="(item.href) ? item.href : '#' " :target="(item.target) ? item.target : '' "
- rel="noreferrer noopener" @click.stop.prevent="item.action">
- <span :class="item.icon" />
- <span v-if="item.text">{{ item.text }}</span>
- <p v-else-if="item.longtext">{{ item.longtext }}</p>
- </a>
- <!-- If item.input is set instead, an put will be used -->
- <span v-else-if="item.input" class="menuitem">
- <!-- does not show if input is checkbox -->
- <span v-if="item.input != 'checkbox'" :class="item.icon" />
- <!-- only shows if input is text -->
- <form v-if="item.input === 'text'"
- :class="item.input" @submit.prevent="item.action">
- <input :type="item.input" :value="item.value" :placeholder="item.placeholder"
- required>
- <input type="submit" value="" class="icon-confirm">
- </form>
- <input v-else :id="key" :type="item.input"
- :class="item.input" v-model="item.model" @change="item.action">
- <label :for="key" @click.stop.prevent="item.action">{{ item.text }}</label>
- </span>
- <!-- If item.action is set instead, a button will be used -->
- <button v-else-if="item.action" @click.stop.prevent="item.action">
- <span :class="item.icon" />
- <span v-if="item.text">{{ item.text }}</span>
- <p v-else-if="item.longtext">{{ item.longtext }}</p>
- </button>
- <!-- If item.longtext is set AND the item does not have an action -->
- <span v-else class="menuitem">
- <span :class="item.icon" />
- <span v-if="item.text">{{ item.text }}</span>
- <p v-else-if="item.longtext">{{ item.longtext }}</p>
- </span>
- </li>
-</template>
-
-<script>
-export default {
- props: {
- item: {
- type: Object,
- default: () => {
- return {
- key: 'nextcloud-link',
- href: 'https://nextcloud.com',
- icon: 'icon-links',
- text: 'Nextcloud'
- }
- },
- required: true
- }
- },
- computed: {
- // random key for inputs binding if not provided
- key() {
- return this.item.key
- ? this.item.key
- : Math.round(Math.random() * 16 * 1000000).toString(16)
- }
- }
-}
-</script>
diff --git a/src/views/Contacts.vue b/src/views/Contacts.vue
index f39ef934..e5c93e8e 100644
--- a/src/views/Contacts.vue
+++ b/src/views/Contacts.vue
@@ -47,11 +47,12 @@
</template>
<script>
-import appNavigation from '../components/core/appNavigation'
-import settingsSection from '../components/SettingsSection'
-import contentList from '../components/ContentList'
-import contactDetails from '../components/ContactDetails'
-import importScreen from '../components/ImportScreen'
+import { AppNavigation } from 'nextcloud-vue'
+
+import SettingsSection from '../components/SettingsSection'
+import ContentList from '../components/ContentList'
+import ContactDetails from '../components/ContactDetails'
+import ImportScreen from '../components/ImportScreen'
import Contact from '../models/contact'
import rfcProps from '../models/rfcProps.js'
@@ -60,11 +61,11 @@ import rfcProps from '../models/rfcProps.js'
export default {
components: {
- appNavigation,
- settingsSection,
- contentList,
- contactDetails,
- importScreen
+ AppNavigation,
+ SettingsSection,
+ ContentList,
+ ContactDetails,
+ ImportScreen
},
// passed by the router