You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

appList.vue 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <!--
  2. - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
  3. -
  4. - @author Julius Härtl <jus@bitgrid.net>
  5. -
  6. - @license GNU AGPL version 3 or any later version
  7. -
  8. - This program is free software: you can redistribute it and/or modify
  9. - it under the terms of the GNU Affero General Public License as
  10. - published by the Free Software Foundation, either version 3 of the
  11. - License, or (at your option) any later version.
  12. -
  13. - This program is distributed in the hope that it will be useful,
  14. - but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. - GNU Affero General Public License for more details.
  17. -
  18. - You should have received a copy of the GNU Affero General Public License
  19. - along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. -
  21. -->
  22. <template>
  23. <div id="app-content-inner">
  24. <div id="apps-list" class="apps-list" :class="{installed: (useBundleView || useListView), store: useAppStoreView}">
  25. <template v-if="useListView">
  26. <transition-group name="app-list" tag="div" class="apps-list-container">
  27. <AppItem v-for="app in apps"
  28. :key="app.id"
  29. :app="app"
  30. :category="category" />
  31. </transition-group>
  32. </template>
  33. <transition-group v-if="useBundleView"
  34. name="app-list"
  35. tag="div"
  36. class="apps-list-container">
  37. <template v-for="bundle in bundles">
  38. <div :key="bundle.id" class="apps-header">
  39. <div class="app-image" />
  40. <h2>{{ bundle.name }} <input type="button" :value="bundleToggleText(bundle.id)" @click="toggleBundle(bundle.id)"></h2>
  41. <div class="app-version" />
  42. <div class="app-level" />
  43. <div class="app-groups" />
  44. <div class="actions">
  45. &nbsp;
  46. </div>
  47. </div>
  48. <AppItem v-for="app in bundleApps(bundle.id)"
  49. :key="bundle.id + app.id"
  50. :app="app"
  51. :category="category" />
  52. </template>
  53. </transition-group>
  54. <template v-if="useAppStoreView">
  55. <AppItem v-for="app in apps"
  56. :key="app.id"
  57. :app="app"
  58. :category="category"
  59. :list-view="false" />
  60. </template>
  61. </div>
  62. <div id="apps-list-search" class="apps-list installed">
  63. <div class="apps-list-container">
  64. <template v-if="search !== '' && searchApps.length > 0">
  65. <div class="section">
  66. <div />
  67. <td colspan="5">
  68. <h2>{{ t('settings', 'Results from other categories') }}</h2>
  69. </td>
  70. </div>
  71. <AppItem v-for="app in searchApps"
  72. :key="app.id"
  73. :app="app"
  74. :category="category"
  75. :list-view="true" />
  76. </template>
  77. </div>
  78. </div>
  79. <div v-if="search !== '' && !loading && searchApps.length === 0 && apps.length === 0" id="apps-list-empty" class="emptycontent emptycontent-search">
  80. <div id="app-list-empty-icon" class="icon-settings-dark" />
  81. <h2>{{ t('settings', 'No apps found for your version') }}</h2>
  82. </div>
  83. <div id="searchresults" />
  84. </div>
  85. </template>
  86. <script>
  87. import AppItem from './AppList/AppItem'
  88. import PrefixMixin from './PrefixMixin'
  89. export default {
  90. name: 'AppList',
  91. components: {
  92. AppItem
  93. },
  94. mixins: [PrefixMixin],
  95. props: ['category', 'app', 'search'],
  96. computed: {
  97. loading() {
  98. return this.$store.getters.loading('list')
  99. },
  100. apps() {
  101. let apps = this.$store.getters.getAllApps
  102. .filter(app => app.name.toLowerCase().search(this.search.toLowerCase()) !== -1)
  103. .sort(function(a, b) {
  104. const sortStringA = '' + (a.active ? 0 : 1) + (a.update ? 0 : 1) + a.name
  105. const sortStringB = '' + (b.active ? 0 : 1) + (b.update ? 0 : 1) + b.name
  106. return OC.Util.naturalSortCompare(sortStringA, sortStringB)
  107. })
  108. if (this.category === 'installed') {
  109. return apps.filter(app => app.installed)
  110. }
  111. if (this.category === 'enabled') {
  112. return apps.filter(app => app.active && app.installed)
  113. }
  114. if (this.category === 'disabled') {
  115. return apps.filter(app => !app.active && app.installed)
  116. }
  117. if (this.category === 'app-bundles') {
  118. return apps.filter(app => app.bundles)
  119. }
  120. if (this.category === 'updates') {
  121. return apps.filter(app => app.update)
  122. }
  123. // filter app store categories
  124. return apps.filter(app => {
  125. return app.appstore && app.category !== undefined
  126. && (app.category === this.category || app.category.indexOf(this.category) > -1)
  127. })
  128. },
  129. bundles() {
  130. return this.$store.getters.getServerData.bundles.filter(bundle => this.bundleApps(bundle.id).length > 0)
  131. },
  132. bundleApps() {
  133. return function(bundle) {
  134. return this.$store.getters.getAllApps
  135. .filter(app => app.bundleId === bundle)
  136. }
  137. },
  138. searchApps() {
  139. if (this.search === '') {
  140. return []
  141. }
  142. return this.$store.getters.getAllApps
  143. .filter(app => {
  144. if (app.name.toLowerCase().search(this.search.toLowerCase()) !== -1) {
  145. return (!this.apps.find(_app => _app.id === app.id))
  146. }
  147. return false
  148. })
  149. },
  150. useAppStoreView() {
  151. return !this.useListView && !this.useBundleView
  152. },
  153. useListView() {
  154. return (this.category === 'installed' || this.category === 'enabled' || this.category === 'disabled' || this.category === 'updates')
  155. },
  156. useBundleView() {
  157. return (this.category === 'app-bundles')
  158. },
  159. allBundlesEnabled() {
  160. let self = this
  161. return function(id) {
  162. return self.bundleApps(id).filter(app => !app.active).length === 0
  163. }
  164. },
  165. bundleToggleText() {
  166. let self = this
  167. return function(id) {
  168. if (self.allBundlesEnabled(id)) {
  169. return t('settings', 'Disable all')
  170. }
  171. return t('settings', 'Enable all')
  172. }
  173. }
  174. },
  175. methods: {
  176. toggleBundle(id) {
  177. if (this.allBundlesEnabled(id)) {
  178. return this.disableBundle(id)
  179. }
  180. return this.enableBundle(id)
  181. },
  182. enableBundle(id) {
  183. let apps = this.bundleApps(id).map(app => app.id)
  184. this.$store.dispatch('enableApp', { appId: apps, groups: [] })
  185. .catch((error) => { console.error(error); OC.Notification.show(error) })
  186. },
  187. disableBundle(id) {
  188. let apps = this.bundleApps(id).map(app => app.id)
  189. this.$store.dispatch('disableApp', { appId: apps, groups: [] })
  190. .catch((error) => { OC.Notification.show(error) })
  191. }
  192. }
  193. }
  194. </script>