Signed-off-by: Marco Ambrosini <marcoambrosini@pm.me>
This commit is contained in:
Marco Ambrosini 2019-09-13 18:28:44 +02:00
Родитель 88d7d7820e
Коммит 5e9c3400c7
18 изменённых файлов: 42690 добавлений и 71 удалений

99
.eslintrc.js Normal file
Просмотреть файл

@ -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"]

2
.gitignore поставляемый
Просмотреть файл

@ -11,3 +11,5 @@ tests/php/coverage-html
tests/php/clover.xml
tests/integration/vendor
tests/integration/output
js

10041
js/Talk.js Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

1
js/Talk.js.map Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

10801
js/talk.js Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

1
js/talk.js.map Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

10041
js/vueexample.js Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

1
js/vueexample.js.map Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

11247
package-lock.json сгенерированный Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

77
package.json Normal 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"
}
}

178
src/App.vue Normal file
Просмотреть файл

@ -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>

102
src/components/Message.vue Normal file
Просмотреть файл

@ -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>

33
src/main.js Normal file
Просмотреть файл

@ -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)
})

Просмотреть файл

@ -2,45 +2,7 @@
/** @var \OCP\IL10N $l */
/** @var array $_ */
style('spreed', 'merged');
script('spreed', 'merged');
script('spreed', 'talk');
\OC::$server->getEventDispatcher()->dispatch('\OCP\Collaboration\Resources::loadAdditionalScripts');
?>
<div id="app" class="nc-enable-screensharing-extension" data-token="<?php p($_['token']) ?>">
<script type="text/json" id="signaling-settings">
<?php echo json_encode($_['signaling-settings']) ?>
</script>
</div>
<div id="app-navigation" class="icon-loading">
<form id="oca-spreedme-add-room">
<input id="select-participants" class="select2-offscreen" type="text" placeholder="<?php p($l->t('New conversation …')) ?>"/>
</form>
<ul id="spreedme-room-list" class="with-icon">
</ul>
</div>
<div id="app-content" class="participants-1">
<div id="app-content-wrapper">
<button id="video-fullscreen" class="icon-fullscreen force-icon-white-in-call icon-shadow hidden" data-placement="bottom" data-toggle="tooltip" data-original-title="<?php p($l->t('Fullscreen (f)')) ?>"></button>
<div id="videos"></div>
<div id="screens"></div>
<div id="emptycontent">
<div id="emptycontent-icon" class="icon-talk"></div>
<h2><?php p($l->t('Join a conversation or start a new one')) ?></h2>
<p class="emptycontent-additional"><?php p($l->t('Say hi to your friends and colleagues!')) ?></p>
<div id="shareRoomContainer" class="" style="display: inline-flex">
<input id="shareRoomInput" class="share-room-input hidden" readonly="readonly" type="text"/>
<div id="shareRoomClipboardButton" class="shareRoomClipboard icon-clippy hidden" data-clipboard-target="#shareRoomInput"></div>
</div>
</div>
</div>
</div>
?>

50
webpack.common.js Normal file
Просмотреть файл

@ -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']
}
}

7
webpack.dev.js Normal file
Просмотреть файл

@ -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',
})

7
webpack.prod.js Normal file
Просмотреть файл

@ -0,0 +1,7 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'production',
devtool: '#source-map'
})