summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2018-10-23 15:38:03 +0200
committerJulius Härtl <jus@bitgrid.net>2018-10-23 22:12:28 +0200
commit29e34e8fea5c957c30e54847a3d3ed0cf6b7e5eb (patch)
tree8418539e87e28915d7d20264caf783a8fd57213c
parent35cc3588080279c0fea116100a5f1016c8b6212c (diff)
Add basic routing and profile info page
Signed-off-by: Julius Härtl <jus@bitgrid.net>
-rw-r--r--.babelrc.js14
-rw-r--r--src/App.vue145
-rw-r--r--src/components/ProfileInfo.vue113
-rw-r--r--src/components/TimelineEntry.vue14
-rw-r--r--src/main.js20
-rw-r--r--src/router.js58
-rw-r--r--src/store/account.js48
-rw-r--r--src/store/index.js12
-rw-r--r--src/store/settings.js38
-rw-r--r--src/views/Profile.vue155
-rw-r--r--src/views/Timeline.vue225
11 files changed, 725 insertions, 117 deletions
diff --git a/.babelrc.js b/.babelrc.js
new file mode 100644
index 00000000..475cfbd7
--- /dev/null
+++ b/.babelrc.js
@@ -0,0 +1,14 @@
+module.exports = {
+ plugins: ['@babel/plugin-syntax-dynamic-import'],
+ presets: [
+ [
+ '@babel/preset-env',
+ {
+ targets: {
+ browsers: ['last 2 versions', 'ie >= 11']
+ }
+ }
+ ]
+ ]
+}
+
diff --git a/src/App.vue b/src/App.vue
index 1f6baeb3..805193f7 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,131 +1,50 @@
<template>
- <div id="content" class="app-social">
- <div id="app-navigation">
+ <div class="app-social">
+ <div id="app-navigation" v-if="!serverData.public">
<app-navigation :menu="menu"></app-navigation>
</div>
<div id="app-content">
- <div class="social__container">
- <div class="social__welcome" v-if="!infoHidden">
- <a class="close icon-close" @click="hideInfo()" href="#"><span class="hidden-visually">Close</span></a>
- <h3>🎉{{ t('social', 'Nextcloud becomes part of the federated social networks!') }}</h3>
- <p>
- {{ t('social', 'We have automatically created a social account for you. Your social id is the same as the federated cloud id:') }}
- <span class="social-id">{{ socialId }}</span>
- </p>
- </div>
- <div class="social__timeline">
- <div class="new-post" data-id="">
- <div class="new-post-author">
- <div class="avatar currentUser" data-username="admin"><img src="/index.php/avatar/admin/32?v=1" alt=""></div>
- </div>
- <form class="new-post-form">
- <div class="author currentUser">
- {{ currentUser.displayName }}
- <span class="social-id">{{ socialId }}</span>
- </div>
- <div contenteditable="true" class="message" placeholder="Share a thought…"></div>
- <input class="submit icon-confirm has-tooltip" type="submit" value="" title="" data-original-title="Post">
- <div class="submitLoading icon-loading-small hidden"></div>
- </form>
- </div>
- <timeline-entry v-for="entry in timeline" :key="entry.id" :item="entry"></timeline-entry>
- </div>
- </div>
+ <router-view :key="$route.fullPath"></router-view>
</div>
</div>
</template>
<style scoped>
- .social__welcome {
- max-width: 700px;
- margin: 15px auto;
- padding: 15px;
- border-radius: 10px;
- background-color: var(--color-background-dark);
- }
-
- .social__welcome h3 {
- margin-top: 0;
- }
-
- .social__welcome .icon-close {
- float:right;
- }
-
- .social__welcome .social-id {
- font-weight: bold;
- }
-
- .social__timeline {
- max-width: 700px;
- margin: 15px auto;
- }
-
- .new-post {
- display: flex;
- padding: 10px;
- background-color: var(--color-main-background);
- position: sticky;
- top: 47px;
- z-index: 100;
- margin-bottom: 10px;
- }
- .new-post-author {
- padding: 5px;
- }
- .author .social-id {
- opacity: .5;
- }
- .new-post-form {
- flex-grow: 1;
- position: relative;
- }
- .message {
+ .app-social {
width: 100%;
}
- [contenteditable=true]:empty:before{
- content: attr(placeholder);
- display: block; /* For Firefox */
- opacity: .5;
- }
- input[type=submit] {
- width: 44px;
- height: 44px;
- margin: 0;
- padding: 13px;
- background-color: transparent;
- border: none;
- opacity: 0.3;
- position: absolute;
- bottom: 0;
- right: 0;
- }
-
- #app-content {
- position: relative;
- }
-
</style>
<script>
import {
PopoverMenu,
- AppNavigation
+ AppNavigation,
+ Multiselect,
+ Avatar
} from 'nextcloud-vue';
import TimelineEntry from './components/TimelineEntry';
+ import ProfileInfo from './components/ProfileInfo';
export default {
name: 'App',
components: {
- PopoverMenu, AppNavigation, TimelineEntry
+ PopoverMenu, AppNavigation, TimelineEntry, Multiselect, Avatar,
+ ProfileInfo
},
data: function () {
return {
infoHidden: false,
+ state: [],
};
},
beforeMount: function() {
+ // importing server data into the store
+ const serverDataElmt = document.getElementById('serverData');
+ if (serverDataElmt !== null) {
+ this.$store.commit('setServerData', JSON.parse(document.getElementById('serverData').dataset.server));
+ }
+
let example = {
message: 'Want to #DropDropbox? #DeleteGoogle? #decentralize? We got you covered, easy as a piece of 🥞\n' +
'\n' +
@@ -136,10 +55,19 @@
timestamp: '1 day ago'
};
let data = [];
- for (let i=0; i<20; i++) {
+ for (let i=0; i<3; i++) {
example.id = Math.floor((Math.random() * 100));
data.push(example);
}
+ data.push({
+ message: 'Want to #DropDropbox? #DeleteGoogle? #decentralize? We got you covered, easy as a piece of 🥞\n' +
+ '\n' +
+ 'Get started right now: https://nextcloud.com/signup',
+ author: 'Admin☁️💻',
+ authorId: 'admin',
+ authorAvatar: OC.linkTo('social', 'img/nextcloud.png'),
+ timestamp: '1 day ago'
+ })
this.$store.commit('addToTimeline', data);
},
methods: {
@@ -148,6 +76,9 @@
}
},
computed: {
+ url: function() {
+ return OC.linkTo('social', 'img/nextcloud.png');
+ },
currentUser: function() {
return OC.getCurrentUser();
},
@@ -157,21 +88,29 @@
timeline: function() {
return this.$store.getters.getTimeline;
},
+ serverData: function() {
+ return this.$store.getters.getServerData;
+ },
menu: function () {
let defaultCategories = [
{
id: 'social-timeline',
classes: [],
- href: '#',
icon: 'icon-category-monitoring',
text: t('social', 'Timeline'),
+ router: {
+ name: 'timeline',
+ },
},
{
- id: 'social-your-posts',
+ id: 'social-account',
classes: [],
- href: '#',
icon: 'icon-user',
- text: t('social', 'Your posts'),
+ text: t('social', 'Your account'),
+ router: {
+ name: 'profile',
+ params: {account: this.currentUser.uid }
+ },
},
{
id: 'social-friends',
diff --git a/src/components/ProfileInfo.vue b/src/components/ProfileInfo.vue
new file mode 100644
index 00000000..7b5b2ab7
--- /dev/null
+++ b/src/components/ProfileInfo.vue
@@ -0,0 +1,113 @@
+<!--
+ - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ -
+ - @author Julius Härtl <jus@bitgrid.net>
+ -
+ - @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 class="user-profile" v-if="uid && accountInfo">
+ <div class="user-profile--info">
+ <avatar :user="profileInfo.uid" :displayName="displayName" :size="128" />
+ <h2 v-if="accountInfo.displayname">{{accountInfo.displayname.value}}</h2>
+ <p>{{accountInfo.cloudId}}</p>
+ <p v-if="accountInfo.website">Website: <a :href="accountInfo.website.value">{{accountInfo.website.value}}</a></p>
+
+ <button v-if="!serverData.public" class="primary" @click="follow">Follow this user</button>
+ </div>
+
+
+ <ul class="user-profile--sections">
+ <li id="social-timeline" class="">
+ <a href="#" class="icon-category-monitoring">{{ accountInfo.posts }} posts</a>
+ </li>
+ <li id="social-timeline" class="">
+ <a href="#" class="icon-category-social">{{ accountInfo.following }} following</a>
+ </li>
+ <li id="social-timeline" class="">
+ <a href="#" class="icon-category-social">{{ accountInfo.followers }} followers</a>
+ </li>
+ </ul>
+ </div>
+</template>
+<style scoped>
+ .user-profile {
+ display: flex;
+ width: 100%;
+ text-align: center;
+ padding-top: 20px;
+ align-items: flex-end;
+ margin-bottom: 20px;
+ }
+ h2 {
+ margin-bottom: 5px;
+ }
+
+ .user-profile--info {
+ width: 40%;
+ }
+ .user-profile--sections {
+ width: 60%;
+ display: flex;
+ margin-bottom: 30px;
+ }
+ .user-profile--sections li {
+ flex-grow: 1;
+ }
+ .user-profile--sections li a {
+ padding-left: 24px;
+ background-position: 0px center;
+ height: 40px;
+ }
+</style>
+<script>
+
+ import { Avatar } from 'nextcloud-vue'
+
+ export default {
+ name: 'ProfileInfo',
+ props: ['uid'],
+ components: {
+ Avatar
+ },
+ methods: {
+ follow() {
+ console.log('TODO: implement following users');
+ }
+ },
+ computed: {
+ displayName() {
+ console.log(this.accountInfo);
+ return this.accountInfo.displayname.value || '';
+ },
+ serverData: function() {
+ return this.$store.getters.getServerData;
+ },
+ accountInfo: function() {
+ return this.$store.getters.getAccount(this.uid);
+ },
+ profileInfo() {
+ return {
+ uid: this.uid,
+ server: OC.getHost()
+ }
+ }
+ }
+ }
+
+</script>
diff --git a/src/components/TimelineEntry.vue b/src/components/TimelineEntry.vue
index 50c1609e..899861d1 100644
--- a/src/components/TimelineEntry.vue
+++ b/src/components/TimelineEntry.vue
@@ -1,11 +1,15 @@
<template>
<div class="timeline-entry">
<div class="entry-content">
- <div class="post-avatar"><img alt="" width="32" height="32" :src="item.authorAvatar"></div>
+ <div class="post-avatar">
+ <avatar :size="32" :url="item.authorAvatar" />
+ </div>
<div class="post-content">
<div class="post-author-wrapper">
- <span class="post-author">{{ item.author }}</span>
- <span class="post-author-id">{{ item.authorId }}</span>
+ <router-link :to="{ name: 'profile', params: { account: item.authorId }}">
+ <span class="post-author">{{ item.author }}</span>
+ <span class="post-author-id">{{ item.authorId }}</span>
+ </router-link>
</div>
<div class="post-message" v-html="formatedMessage">
</div>
@@ -16,11 +20,13 @@
</template>
<script>
+ import { Avatar } from 'nextcloud-vue'
+
export default {
name: 'TimelineEntry',
props: ['item'],
components: {
-
+ Avatar
},
data: function () {
return {
diff --git a/src/main.js b/src/main.js
index 892e527b..5f9d65a0 100644
--- a/src/main.js
+++ b/src/main.js
@@ -19,12 +19,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+import "@babel/polyfill";
import Vue from 'vue'
-import App from './App'
+import {sync} from 'vuex-router-sync';
+import App from './App'
import store from './store';
+import router from './router';
+
+sync(store, router);
+
+// CSP config for webpack dynamic chunk loading
+// eslint-disable-next-line
+__webpack_nonce__ = btoa(OC.requestToken)
+// Correct the root of the app for chunk loading
+// OC.linkTo matches the apps folders
+// eslint-disable-next-line
+__webpack_public_path__ = OC.linkTo('social', 'js/')
Vue.prototype.t = t
Vue.prototype.n = n
@@ -33,6 +46,7 @@ Vue.prototype.OCA = OCA
/* eslint-disable-next-line no-new */
new Vue({
- render: h => h(App),
+ router: router,
+ render: h => h(App),
store: store
-}).$mount('#content')
+}).$mount('#vue-content')
diff --git a/src/router.js b/src/router.js
new file mode 100644
index 00000000..4758068d
--- /dev/null
+++ b/src/router.js
@@ -0,0 +1,58 @@
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ * @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/>.
+ *
+ */
+import Vue from 'vue';
+import Router from 'vue-router';
+
+// Dynamic loading
+const Timeline = () => import('./views/Timeline');
+const Profile = () => import('./views/Profile');
+Vue.use(Router);
+
+export default new Router({
+ mode: 'history',
+ // if index.php is in the url AND we got this far, then it's working:
+ // let's keep using index.php in the url
+ base: OC.generateUrl(''),
+ linkActiveClass: 'active',
+ routes: [
+ {
+ path: '/:index(index.php/)?apps/social/',
+ component: Timeline,
+ props: true,
+ name: 'timeline'
+ },
+ {
+ path: '/:index(index.php/)?apps/social/account/:account',
+ component: Profile,
+ props: true,
+ name: 'profile',
+ },
+ {
+ path: '/:index(index.php/)?apps/social/:account',
+ component: Profile,
+ props: true,
+ name: 'public',
+ }
+ ]
+});
diff --git a/src/store/account.js b/src/store/account.js
new file mode 100644
index 00000000..e1adaac0
--- /dev/null
+++ b/src/store/account.js
@@ -0,0 +1,48 @@
+/*
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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/>.
+ *
+ */
+
+import axios from 'nextcloud-axios';
+import Vue from 'vue';
+
+const state = {
+ accounts: {}
+};
+const mutations = {
+ addAccount(state, {uid, data}) {
+ Vue.set(state.accounts, uid, data);
+ }
+};
+const getters = {
+ getAccount(state) {
+ return (uid) => state.accounts[uid];
+ }
+};
+const actions = {
+ fetchAccountInfo(context, uid) {
+ axios.get(OC.generateUrl('apps/social/local/account/' + uid)).then((response) => {
+ console.log(response.data);
+ context.commit('addAccount', {uid: uid, data:response.data});
+ });
+ }
+};
+
+export default {state, mutations, getters, actions};
diff --git a/src/store/index.js b/src/store/index.js
index 061ad400..72cc73de 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -24,20 +24,18 @@
import Vue from 'vue';
import Vuex from 'vuex';
import timeline from './timeline';
+import account from './account';
+import settings from './settings';
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production';
-const mutations = {
-
-};
-
export default new Vuex.Store({
modules: {
- timeline
+ timeline,
+ account,
+ settings
},
strict: debug,
-
- mutations
});
diff --git a/src/store/settings.js b/src/store/settings.js
new file mode 100644
index 00000000..10fcbe5b
--- /dev/null
+++ b/src/store/settings.js
@@ -0,0 +1,38 @@
+/*
+ * @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/>.
+ *
+ */
+
+const state = {
+ serverData: {}
+};
+const mutations = {
+ setServerData(state, data) {
+ state.serverData = data;
+ }
+};
+const getters = {
+ getServerData(state) {
+ return state.serverData;
+ }
+};
+const actions = {};
+
+export default {state, mutations, getters, actions};
diff --git a/src/views/Profile.vue b/src/views/Profile.vue
new file mode 100644
index 00000000..27215af7
--- /dev/null
+++ b/src/views/Profile.vue
@@ -0,0 +1,155 @@
+<!--
+ - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ -
+ - @author Julius Härtl <jus@bitgrid.net>
+ -
+ - @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 class="social__wrapper">
+ <profile-info :uid="uid"></profile-info>
+ <div class="social__container">
+ <div class="social__timeline">
+ <timeline-entry v-for="entry in timeline" :item="entry"></timeline-entry>
+ </div>
+ </div>
+ </div>
+</template>
+
+<style scoped>
+ .social__wrapper {
+ max-width: 700px;
+ margin: 15px auto;
+ }
+
+ .social__welcome {
+ max-width: 700px;
+ margin: 15px auto;
+ padding: 15px;
+ border-radius: 10px;
+ background-color: var(--color-background-dark);
+ }
+
+ .social__welcome h3 {
+ margin-top: 0;
+ }
+
+ .social__welcome .icon-close {
+ float:right;
+ }
+
+ .social__welcome .social-id {
+ font-weight: bold;
+ }
+
+ .social__timeline {
+ max-width: 700px;
+ margin: 15px auto;
+ }
+
+ .new-post {
+ display: flex;
+ padding: 10px;
+ background-color: var(--color-main-background);
+ position: sticky;
+ top: 47px;
+ z-index: 100;
+ margin-bottom: 10px;
+ }
+ .new-post-author {
+ padding: 5px;
+ }
+ .author .social-id {
+ opacity: .5;
+ }
+ .new-post-form {
+ flex-grow: 1;
+ position: relative;
+ }
+ .message {
+ width: 100%;
+ }
+ [contenteditable=true]:empty:before{
+ content: attr(placeholder);
+ display: block; /* For Firefox */
+ opacity: .5;
+ }
+ input[type=submit] {
+ width: 44px;
+ height: 44px;
+ margin: 0;
+ padding: 13px;
+ background-color: transparent;
+ border: none;
+ opacity: 0.3;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ }
+
+ #app-content {
+ position: relative;
+ }
+
+</style>
+
+
+<script>
+ import {
+ PopoverMenu,
+ AppNavigation,
+ Multiselect,
+ Avatar
+ } from 'nextcloud-vue';
+ import TimelineEntry from './../components/TimelineEntry';
+ import ProfileInfo from './../components/ProfileInfo';
+
+ export default {
+ name: 'Timeline',
+ components: {
+ PopoverMenu, AppNavigation, TimelineEntry, Multiselect, Avatar,
+ ProfileInfo
+ },
+ beforeMount() {
+ this.uid = this.$route.params.account;
+ this.$store.dispatch('fetchAccountInfo', this.uid);
+ },
+ data: function () {
+ return {
+ state: [],
+ uid: null,
+ };
+ },
+ methods: {
+ },
+ computed: {
+ serverData: function() {
+ return this.$store.getters.getServerData;
+ },
+ currentUser: function() {
+ return OC.getCurrentUser();
+ },
+ socialId: function() {
+ return '@' + OC.getCurrentUser().uid + '@' + OC.getHost();
+ },
+ timeline: function() {
+ return this.$store.getters.getTimeline;
+ }
+ }
+ }
+</script>
diff --git a/src/views/Timeline.vue b/src/views/Timeline.vue
new file mode 100644
index 00000000..503e34bf
--- /dev/null
+++ b/src/views/Timeline.vue
@@ -0,0 +1,225 @@
+<template>
+ <div class="social__wrapper">
+ <div class="social__container">
+ <div class="social__welcome" v-if="!infoHidden">
+ <a class="close icon-close" @click="hideInfo()" href="#"><span class="hidden-visually">Close</span></a>
+ <h3>🎉{{ t('social', 'Nextcloud becomes part of the federated social networks!') }}</h3>
+ <p>
+ {{ t('social', 'We have automatically created a social account for you. Your social id is the same as the federated cloud id:') }}
+ <span class="social-id">{{ socialId }}</span>
+ </p>
+ </div>
+ <div class="social__timeline">
+ <div class="new-post" data-id="">
+ <div class="new-post-author">
+ <avatar :user="currentUser.uid" :displayName="currentUser.displayName" :size="32" />
+ </div>
+ <form class="new-post-form">
+ <div class="author currentUser">
+ {{ currentUser.displayName }}
+ <span class="social-id">{{ socialId }}</span>
+ </div>
+ <div contenteditable="true" class="message" placeholder="Share a thought…"></div>
+ <input class="submit icon-confirm has-tooltip" type="submit" value="" title="" data-original-title="Post">
+ <div class="submitLoading icon-loading-small hidden"></div>
+ </form>
+ </div>
+ <timeline-entry v-for="entry in timeline" :item="entry"></timeline-entry>
+ </div>
+ </div>
+ </div>
+</template>
+
+<style scoped>
+ .social__wrapper {
+ display: flex;
+ }
+
+ .social__container {
+ flex-grow: 1;
+ }
+ .social__profile {
+ max-width: 500px;
+ flex-grow: 1;
+ border-right: 1px solid var(--color-background-dark);
+ text-align: center;
+ padding-top: 20px;
+ }
+ .social__welcome {
+ max-width: 700px;
+ margin: 15px auto;
+ padding: 15px;
+ border-radius: 10px;
+ background-color: var(--color-background-dark);
+ }
+
+ .social__welcome h3 {
+ margin-top: 0;
+ }
+
+ .social__welcome .icon-close {
+ float:right;
+ }
+
+ .social__welcome .social-id {
+ font-weight: bold;
+ }
+
+ .social__timeline {
+ max-width: 700px;
+ margin: 15px auto;
+ }
+
+ .new-post {
+ display: flex;
+ padding: 10px;
+ background-color: var(--color-main-background);
+ position: sticky;
+ top: 47px;
+ z-index: 100;
+ margin-bottom: 10px;
+ }
+ .new-post-author {
+ padding: 5px;
+ }
+ .author .social-id {
+ opacity: .5;
+ }
+ .new-post-form {
+ flex-grow: 1;
+ position: relative;
+ }
+ .message {
+ width: 100%;
+ }
+ [contenteditable=true]:empty:before{
+ content: attr(placeholder);
+ display: block; /* For Firefox */
+ opacity: .5;
+ }
+ input[type=submit] {
+ width: 44px;
+ height: 44px;
+ margin: 0;
+ padding: 13px;
+ background-color: transparent;
+ border: none;
+ opacity: 0.3;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ }
+
+ #app-content {
+ position: relative;
+ }
+
+</style>
+
+
+<script>
+ import {
+ PopoverMenu,
+ AppNavigation,
+ Multiselect,
+ Avatar
+ } from 'nextcloud-vue';
+ import TimelineEntry from './../components/TimelineEntry';
+
+ export default {
+ name: 'Timeline',
+ components: {
+ PopoverMenu, AppNavigation, TimelineEntry, Multiselect, Avatar
+ },
+ data: function () {
+ return {
+ infoHidden: false,
+ state: [],
+ };
+ },
+ beforeMount: function() {
+ let example = {
+ message: 'Want to #DropDropbox? #DeleteGoogle? #decentralize? We got you covered, easy as a piece of 🥞\n' +
+ '\n' +
+ 'Get started right now: https://nextcloud.com/signup',
+ author: 'Nextcloud 📱☁️💻',
+ authorId: '@nextcloud@mastodon.xyz',
+ authorAvatar: OC.linkTo('social', 'img/nextcloud.png'),
+ timestamp: '1 day ago'
+ };
+ let data = [];
+ for (let i=0; i<20; i++) {
+ let item = Object.assign({}, example);
+ item.id = i;
+ data.push(item);
+ }
+ console.log(data);
+ this.$store.commit('addToTimeline', data);
+ },
+ methods: {
+ hideInfo() {
+ this.infoHidden = true;
+ }
+ },
+ computed: {
+ url: function() {
+ return OC.linkTo('social', 'img/nextcloud.png');
+ },
+ currentUser: function() {
+ return OC.getCurrentUser();
+ },
+ socialId: function() {
+ return '@' + OC.getCurrentUser().uid + '@' + OC.getHost();
+ },
+ timeline: function() {
+ return this.$store.getters.getTimeline;
+ },
+ menu: function () {
+ let defaultCategories = [
+ {
+ id: 'social-timeline',
+ classes: [],
+ href: '#',
+ icon: 'icon-category-monitoring',
+