Browse Source
Create Message component
Create Message component
Signed-off-by: Marco Ambrosini <marcoambrosini@pm.me>pull/2185/head
18 changed files with 42690 additions and 71 deletions
-
99.eslintrc.js
-
31.eslintrc.yml
-
2.gitignore
-
10041js/Talk.js
-
1js/Talk.js.map
-
10801js/talk.js
-
1js/talk.js.map
-
10041js/vueexample.js
-
1js/vueexample.js.map
-
11247package-lock.json
-
77package.json
-
178src/App.vue
-
102src/components/Message.vue
-
33src/main.js
-
42templates/index.php
-
50webpack.common.js
-
7webpack.dev.js
-
7webpack.prod.js
@ -0,0 +1,99 @@ |
|||
module.exports = { |
|||
root: true, |
|||
env: { |
|||
browser: true, |
|||
es6: true, |
|||
node: true, |
|||
jest: true |
|||
}, |
|||
globals: { |
|||
t: true, |
|||
n: true, |
|||
OC: true, |
|||
OCA: true, |
|||
Vue: true, |
|||
VueRouter: true |
|||
}, |
|||
parserOptions: { |
|||
parser: 'babel-eslint', |
|||
ecmaVersion: 6 |
|||
}, |
|||
extends: [ |
|||
'eslint:recommended', |
|||
'plugin:import/errors', |
|||
'plugin:import/warnings', |
|||
'plugin:node/recommended', |
|||
'plugin:vue/essential', |
|||
'plugin:vue/recommended', |
|||
'plugin:nextcloud/recommended', |
|||
'standard' |
|||
], |
|||
settings: { |
|||
'import/resolver': { |
|||
webpack: { |
|||
config: 'webpack.common.js' |
|||
}, |
|||
node: { |
|||
paths: ['src'], |
|||
extensions: ['.js', '.vue'] |
|||
} |
|||
} |
|||
}, |
|||
plugins: ['vue', 'node'], |
|||
rules: { |
|||
// space before function ()
|
|||
'space-before-function-paren': ['error', 'never'], |
|||
// curly braces always space
|
|||
'object-curly-spacing': ['error', 'always'], |
|||
// stay consistent with array brackets
|
|||
'array-bracket-newline': ['error', 'consistent'], |
|||
// 1tbs brace style
|
|||
'brace-style': 'error', |
|||
// tabs only
|
|||
indent: ['error', 'tab'], |
|||
'no-tabs': ['off'], |
|||
'vue/html-indent': ['error', 'tab'], |
|||
// only debug console
|
|||
'no-console': ['error', { allow: ['error', 'warn', 'info', 'debug'] }], |
|||
// classes blocks
|
|||
'padded-blocks': ['error', { classes: 'always' }], |
|||
// always have the operator in front
|
|||
'operator-linebreak': ['error', 'before'], |
|||
// ternary on multiline
|
|||
'multiline-ternary': ['error', 'always-multiline'], |
|||
// force proper JSDocs
|
|||
'valid-jsdoc': [2, { |
|||
'prefer': { |
|||
'return': 'returns' |
|||
}, |
|||
'requireReturn': false, |
|||
'requireReturnDescription': false |
|||
}], |
|||
// es6 import/export and require
|
|||
'node/no-unpublished-require': ['off'], |
|||
'node/no-unsupported-features/es-syntax': ['off'], |
|||
// PascalCase components names for vuejs
|
|||
// https://vuejs.org/v2/style-guide/#Single-file-component-filename-casing-strongly-recommended
|
|||
'vue/component-name-in-template-casing': ['error', 'PascalCase'], |
|||
// force name
|
|||
'vue/match-component-file-name': ['error', { |
|||
'extensions': ['jsx', 'vue', 'js'], |
|||
'shouldMatchCase': true |
|||
}], |
|||
// space before self-closing elements
|
|||
'vue/html-closing-bracket-spacing': 'error', |
|||
// no ending html tag on a new line
|
|||
'vue/html-closing-bracket-newline': ['error', { multiline: 'never' }], |
|||
// code spacing with attributes
|
|||
'vue/max-attributes-per-line': [ |
|||
'error', |
|||
{ |
|||
singleline: 3, |
|||
multiline: { |
|||
max: 3, |
|||
allowFirstLine: true |
|||
} |
|||
} |
|||
] |
|||
} |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
root: true |
|||
|
|||
extends: |
|||
- eslint:recommended |
|||
|
|||
env: |
|||
browser: true |
|||
amd: true |
|||
|
|||
globals: |
|||
$: false |
|||
escapeHTML: false |
|||
OC: false |
|||
OCA: false |
|||
t: false |
|||
Backbone: false |
|||
_: false |
|||
Clipboard: false |
|||
oc_defaults: false |
|||
Hashes: false |
|||
|
|||
rules: |
|||
curly: error |
|||
eqeqeq: ["error", "smart"] |
|||
guard-for-in: error |
|||
no-console: off |
|||
no-fallthrough: error |
|||
no-mixed-spaces-and-tabs: error |
|||
no-unused-vars: error |
|||
no-use-before-define: error |
|||
semi: ["error", "always"] |
|||
10041
js/Talk.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
js/Talk.js.map
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
10801
js/talk.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
js/talk.js.map
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
10041
js/vueexample.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
js/vueexample.js.map
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
11247
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,77 @@ |
|||
{ |
|||
"name": "talk", |
|||
"description": "A simple Nextcloud app using vue-components", |
|||
"version": "3.2.0", |
|||
"author": "John Molakvoæ <skjnldsv@protonmail.com>", |
|||
"contributors": [ |
|||
"John Molakvoæ <skjnldsv@protonmail.com>" |
|||
], |
|||
"keywords": [ |
|||
"nextcloud", |
|||
"vueexample", |
|||
"app", |
|||
"dev", |
|||
"vuejs" |
|||
], |
|||
"bugs": { |
|||
"url": "https://github.com/skjnldsv/vueexample/issues" |
|||
}, |
|||
"repository": { |
|||
"url": "https://github.com/skjnldsv/vueexample", |
|||
"type": "git" |
|||
}, |
|||
"homepage": "https://github.com/skjnldsv/vueexample", |
|||
"license": "agpl", |
|||
"private": true, |
|||
"scripts": { |
|||
"dev": "webpack --config webpack.dev.js", |
|||
"watch": "webpack --progress --watch --config webpack.dev.js", |
|||
"build": "webpack --progress --hide-modules --config webpack.prod.js", |
|||
"lint": "eslint --ext .js,.vue src", |
|||
"lint:fix": "eslint --ext .js,.vue src --fix", |
|||
"stylelint": "stylelint src", |
|||
"stylelint:fix": "stylelint src --fix" |
|||
}, |
|||
"dependencies": { |
|||
"nextcloud-vue": "^0.12.3", |
|||
"vue": "^2.6.10" |
|||
}, |
|||
"browserslist": [ |
|||
"extends browserslist-config-nextcloud" |
|||
], |
|||
"engines": { |
|||
"node": ">=10.0.0" |
|||
}, |
|||
"devDependencies": { |
|||
"@babel/core": "^7.6.0", |
|||
"@babel/plugin-syntax-dynamic-import": "^7.2.0", |
|||
"@babel/preset-env": "^7.6.0", |
|||
"@vue/test-utils": "^1.0.0-beta.29", |
|||
"babel-eslint": "^10.0.3", |
|||
"babel-loader": "^8.0.6", |
|||
"browserslist-config-nextcloud": "0.0.1", |
|||
"css-loader": "^3.2.0", |
|||
"eslint": "^5.16.0", |
|||
"eslint-config-standard": "^12.0.0", |
|||
"eslint-import-resolver-webpack": "^0.11.1", |
|||
"eslint-loader": "^3.0.0", |
|||
"eslint-plugin-import": "^2.18.2", |
|||
"eslint-plugin-nextcloud": "^0.3.0", |
|||
"eslint-plugin-node": "^9.2.0", |
|||
"eslint-plugin-promise": "^4.2.1", |
|||
"eslint-plugin-standard": "^4.0.1", |
|||
"eslint-plugin-vue": "^5.2.3", |
|||
"node-sass": "^4.12.0", |
|||
"sass-loader": "^7.3.1", |
|||
"stylelint": "^8.4.0", |
|||
"stylelint-config-recommended-scss": "^3.3.0", |
|||
"stylelint-scss": "^3.10.1", |
|||
"stylelint-webpack-plugin": "^0.10.5", |
|||
"vue-loader": "^15.7.1", |
|||
"vue-template-compiler": "^2.6.10", |
|||
"webpack": "^4.40.1", |
|||
"webpack-cli": "^3.3.8", |
|||
"webpack-merge": "^4.2.2", |
|||
"webpack-node-externals": "^1.7.2" |
|||
} |
|||
} |
|||
@ -0,0 +1,178 @@ |
|||
<template> |
|||
<Content :class="{'icon-loading': loading}" app-name="vueexample"> |
|||
<AppNavigation> |
|||
<AppNavigationNew v-if="!loading" :text="t('vueexample', 'New XXXXXX')" :disabled="false" |
|||
button-id="new-vueexample-button" button-class="icon-add" @click="newButtonAction" /> |
|||
<ul id="app-vueexample-navigation"> |
|||
<AppNavigationItem v-for="item in menu" :key="item.key" :item="item" /> |
|||
</ul> |
|||
<AppNavigationSettings> |
|||
Example settings |
|||
</AppNavigationSettings> |
|||
</AppNavigation> |
|||
<AppContent> |
|||
<span>This is the content</span> |
|||
<button @click="show = !show"> |
|||
Toggle sidebar |
|||
</button> |
|||
<Message |
|||
user-name="Barthelemy dsflkjds" |
|||
:is-first-message="true" |
|||
message-time="16:12" |
|||
message-text="This is a test message" /> |
|||
</AppContent> |
|||
<AppSidebar v-show="show" title="christmas-image-2018-12-25-00:01:12.jpg" subtitle="4,3 MB, last edited 41 days ago" |
|||
:actions="menu" :starred.sync="starred" |
|||
@close="show=false"> |
|||
<template #action> |
|||
<button class="primary"> |
|||
Button 1 |
|||
</button> |
|||
<input id="link-checkbox" name="link-checkbox" class="checkbox link-checkbox" |
|||
type="checkbox"> |
|||
<label for="link-checkbox" class="link-checkbox-label">Do something</label> |
|||
</template> |
|||
<AppSidebarTab name="Chat" icon="icon-talk"> |
|||
this is the chat tab |
|||
</AppSidebarTab> |
|||
<AppSidebarTab name="Activity" icon="icon-activity"> |
|||
this is the activity tab |
|||
</AppSidebarTab> |
|||
<AppSidebarTab name="Comments" icon="icon-comment"> |
|||
this is the comments tab |
|||
</AppSidebarTab> |
|||
<AppSidebarTab name="Sharing" icon="icon-shared"> |
|||
this is the sharing tab |
|||
</AppSidebarTab> |
|||
<AppSidebarTab name="Versions" icon="icon-history"> |
|||
this is the versions tab |
|||
</AppSidebarTab> |
|||
</AppSidebar> |
|||
</Content> |
|||
</template> |
|||
|
|||
<script> |
|||
import Content from 'nextcloud-vue/dist/Components/Content' |
|||
import AppContent from 'nextcloud-vue/dist/Components/AppContent' |
|||
import AppNavigation from 'nextcloud-vue/dist/Components/AppNavigation' |
|||
import AppNavigationItem from 'nextcloud-vue/dist/Components/AppNavigationItem' |
|||
import AppNavigationNew from 'nextcloud-vue/dist/Components/AppNavigationNew' |
|||
import AppNavigationSettings from 'nextcloud-vue/dist/Components/AppNavigationSettings' |
|||
import AppSidebar from 'nextcloud-vue/dist/Components/AppSidebar' |
|||
import AppSidebarTab from 'nextcloud-vue/dist/Components/AppSidebarTab' |
|||
import Message from './components/Message' |
|||
|
|||
export default { |
|||
name: 'App', |
|||
components: { |
|||
Content, |
|||
AppContent, |
|||
AppNavigation, |
|||
AppNavigationItem, |
|||
AppNavigationNew, |
|||
AppNavigationSettings, |
|||
AppSidebar, |
|||
AppSidebarTab, |
|||
Message |
|||
}, |
|||
data: function() { |
|||
return { |
|||
loading: false, |
|||
date: Date.now() + 86400000 * 3, |
|||
date2: Date.now() + 86400000 * 3 + Math.floor(Math.random() * 86400000 / 2), |
|||
show: true, |
|||
starred: false |
|||
} |
|||
}, |
|||
computed: { |
|||
// App navigation |
|||
menu: function() { |
|||
return [ |
|||
{ |
|||
id: 'app-category-your-apps', |
|||
classes: [], |
|||
href: '#1', |
|||
// action: this.log, |
|||
icon: 'icon-category-installed', |
|||
text: t('settings', 'Your apps') |
|||
}, |
|||
{ |
|||
caption: true, |
|||
text: t('vueexample', 'Section') |
|||
}, |
|||
{ |
|||
id: 'app-category-enabled', |
|||
classes: [], |
|||
icon: 'icon-category-enabled', |
|||
href: '#2', |
|||
utils: { |
|||
actions: [{ |
|||
icon: 'icon-delete', |
|||
text: t('settings', 'Remove group'), |
|||
action: function() { |
|||
alert('remove') |
|||
} |
|||
}] |
|||
}, |
|||
text: t('settings', 'Active apps') |
|||
}, |
|||
{ |
|||
id: 'app-category-enabled', |
|||
classes: [], |
|||
icon: 'icon-category-enabled', |
|||
href: '#3', |
|||
utils: { |
|||
counter: 123, |
|||
actions: [ |
|||
{ |
|||
icon: 'icon-delete', |
|||
text: t('settings', 'Remove group'), |
|||
action: function() { |
|||
alert('remove') |
|||
} |
|||
}, |
|||
{ |
|||
icon: 'icon-delete', |
|||
text: t('settings', 'Remove group'), |
|||
action: function() { |
|||
alert('remove') |
|||
} |
|||
} |
|||
] |
|||
}, |
|||
text: t('settings', 'Active apps') |
|||
}, |
|||
{ |
|||
id: 'app-category-disabled', |
|||
classes: [], |
|||
icon: 'icon-category-disabled', |
|||
href: '#4', |
|||
undo: true, |
|||
text: t('settings', 'Disabled apps') |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
methods: { |
|||
addOption(val) { |
|||
this.options.push(val) |
|||
this.select.push(val) |
|||
}, |
|||
previous(data) { |
|||
console.debug(data) |
|||
}, |
|||
next(data) { |
|||
console.debug(data) |
|||
}, |
|||
close(data) { |
|||
console.debug(data) |
|||
}, |
|||
newButtonAction(e) { |
|||
console.debug(e) |
|||
}, |
|||
log(e) { |
|||
console.debug(e) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,102 @@ |
|||
<!-- |
|||
- @copyright Copyright (c) 2019 Marco Ambrosini <marcoambrosini@pm.me> |
|||
- |
|||
- @author Marco Ambrosini <marcoambrosini@pm.me> |
|||
- |
|||
- @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="message"> |
|||
<div class="message-avatar"> |
|||
<Avatar v-if="isFirstMessage" :user="userName" :display-name="userName" /> |
|||
</div> |
|||
<div class="message-main"> |
|||
<div v-if="isFirstMessage" class="message-main-header"> |
|||
<h6>{{ userName }}</h6> |
|||
</div> |
|||
<div class="message-main-text"> |
|||
<p>{{messageText}}</p> |
|||
</div> |
|||
</div> |
|||
<div class="message-right"> |
|||
<h6>{{ messageTime }}</h6> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import Avatar from 'nextcloud-vue/dist/Components/Avatar' |
|||
|
|||
export default { |
|||
name: 'Message', |
|||
components: { |
|||
Avatar |
|||
}, |
|||
props: { |
|||
userName: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
messageTime: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
messageText: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
isFirstMessage: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
|
|||
.message { |
|||
display: flex; |
|||
width: 100%; |
|||
max-width: 600px; |
|||
padding: 12px 0 12px 0; |
|||
margin: auto; |
|||
&-avatar { |
|||
width: 52px; |
|||
min-width: 52px; |
|||
padding: 4px 8px 0 8px; |
|||
} |
|||
&-main { |
|||
display: flex; |
|||
flex-grow: 1; |
|||
flex-direction: column; |
|||
font-size: 20; |
|||
&-header { |
|||
color: #989898; |
|||
} |
|||
&-text { |
|||
color: #000000; |
|||
} |
|||
} |
|||
&-right { |
|||
min-width: 90px; |
|||
color: #989898; |
|||
padding: 0px 8px 0 8px; |
|||
} |
|||
} |
|||
|
|||
</style> |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* @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/>.
|
|||
* |
|||
*/ |
|||
import Vue from 'vue' |
|||
import App from './App' |
|||
|
|||
Vue.prototype.t = t |
|||
Vue.prototype.n = n |
|||
Vue.prototype.OC = OC |
|||
Vue.prototype.OCA = OCA |
|||
|
|||
export default new Vue({ |
|||
el: '#content', |
|||
render: h => h(App) |
|||
}) |
|||
@ -0,0 +1,50 @@ |
|||
const path = require('path') |
|||
const { VueLoaderPlugin } = require('vue-loader') |
|||
const StyleLintPlugin = require('stylelint-webpack-plugin') |
|||
const packageJson = require('./package.json') |
|||
const appName = packageJson.name |
|||
|
|||
module.exports = { |
|||
entry: path.join(__dirname, 'src', 'main.js'), |
|||
output: { |
|||
path: path.resolve(__dirname, './js'), |
|||
publicPath: '/js/', |
|||
filename: `${appName}.js`, |
|||
chunkFilename: 'chunks/[name]-[hash].js' |
|||
}, |
|||
module: { |
|||
rules: [ |
|||
{ |
|||
test: /\.css$/, |
|||
use: ['vue-style-loader', 'css-loader'] |
|||
}, |
|||
{ |
|||
test: /\.scss$/, |
|||
use: ['vue-style-loader', 'css-loader', 'sass-loader'] |
|||
}, |
|||
{ |
|||
test: /\.(js|vue)$/, |
|||
use: 'eslint-loader', |
|||
exclude: /node_modules/, |
|||
enforce: 'pre' |
|||
}, |
|||
{ |
|||
test: /\.vue$/, |
|||
loader: 'vue-loader', |
|||
exclude: /node_modules/ |
|||
}, |
|||
{ |
|||
test: /\.js$/, |
|||
loader: 'babel-loader', |
|||
exclude: /node_modules/ |
|||
} |
|||
] |
|||
}, |
|||
plugins: [ |
|||
new VueLoaderPlugin(), |
|||
new StyleLintPlugin() |
|||
], |
|||
resolve: { |
|||
extensions: ['*', '.js', '.vue'] |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
const merge = require('webpack-merge'); |
|||
const common = require('./webpack.common.js'); |
|||
|
|||
module.exports = merge(common, { |
|||
mode: 'development', |
|||
devtool: '#cheap-source-map', |
|||
}) |
|||
@ -0,0 +1,7 @@ |
|||
const merge = require('webpack-merge') |
|||
const common = require('./webpack.common.js') |
|||
|
|||
module.exports = merge(common, { |
|||
mode: 'production', |
|||
devtool: '#source-map' |
|||
}) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue