kopia lustrzana https://github.com/nextcloud/social
Merge pull request #1580 from nextcloud/artonge/ci/add_es_and_style_lint
Add ES and style lint workflowspull/1568/head
commit
f56e326f80
|
@ -1,8 +1,8 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: [
|
||||||
'@nextcloud'
|
'@nextcloud',
|
||||||
],
|
],
|
||||||
globals: {
|
globals: {
|
||||||
appName: true
|
appName: true,
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
# This workflow is provided via the organization template repository
|
||||||
|
#
|
||||||
|
# https://github.com/nextcloud/.github
|
||||||
|
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||||
|
|
||||||
|
name: Lint
|
||||||
|
|
||||||
|
on: pull_request
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: lint-eslint-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
name: eslint
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Read package.json node and npm engines version
|
||||||
|
uses: skjnldsv/read-package-engines-version-actions@v1.2
|
||||||
|
id: versions
|
||||||
|
with:
|
||||||
|
fallbackNode: '^12'
|
||||||
|
fallbackNpm: '^6'
|
||||||
|
|
||||||
|
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||||
|
|
||||||
|
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
|
||||||
|
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: npm run lint
|
|
@ -0,0 +1,46 @@
|
||||||
|
# This workflow is provided via the organization template repository
|
||||||
|
#
|
||||||
|
# https://github.com/nextcloud/.github
|
||||||
|
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||||
|
|
||||||
|
name: Lint
|
||||||
|
|
||||||
|
on: pull_request
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: lint-stylelint-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
name: stylelint
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Read package.json node and npm engines version
|
||||||
|
uses: skjnldsv/read-package-engines-version-actions@v1.2
|
||||||
|
id: versions
|
||||||
|
with:
|
||||||
|
fallbackNode: '^12'
|
||||||
|
fallbackNpm: '^6'
|
||||||
|
|
||||||
|
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||||
|
|
||||||
|
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
|
||||||
|
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: npm run stylelint
|
Plik diff jest za duży
Load Diff
|
@ -23,6 +23,8 @@
|
||||||
"serve": "NODE_ENV=development webpack serve --progress --config webpack.common.js",
|
"serve": "NODE_ENV=development webpack serve --progress --config webpack.common.js",
|
||||||
"lint": "eslint --ext .js,.vue src",
|
"lint": "eslint --ext .js,.vue src",
|
||||||
"lint:fix": "eslint --ext .js,.vue src --fix",
|
"lint:fix": "eslint --ext .js,.vue src --fix",
|
||||||
|
"stylelint": "stylelint src",
|
||||||
|
"stylelint:fix": "stylelint src --fix",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:coverage": "jest --coverage",
|
"test:coverage": "jest --coverage",
|
||||||
"cypress": "./cypress/start.sh; cypress run; ./cypress/stop.sh",
|
"cypress": "./cypress/start.sh; cypress run; ./cypress/stop.sh",
|
||||||
|
@ -38,7 +40,6 @@
|
||||||
"@nextcloud/logger": "^2.5.0",
|
"@nextcloud/logger": "^2.5.0",
|
||||||
"@nextcloud/moment": "^1.2.1",
|
"@nextcloud/moment": "^1.2.1",
|
||||||
"@nextcloud/router": "^2.0.1",
|
"@nextcloud/router": "^2.0.1",
|
||||||
"@nextcloud/stylelint-config": "^2.3.0",
|
|
||||||
"@nextcloud/vue": "^7.4.0",
|
"@nextcloud/vue": "^7.4.0",
|
||||||
"@nextcloud/vue-richtext": "^2.0.4",
|
"@nextcloud/vue-richtext": "^2.0.4",
|
||||||
"he": "^1.2.0",
|
"he": "^1.2.0",
|
||||||
|
@ -77,6 +78,7 @@
|
||||||
"@nextcloud/babel-config": "^1.0.0",
|
"@nextcloud/babel-config": "^1.0.0",
|
||||||
"@nextcloud/browserslist-config": "^2.3.0",
|
"@nextcloud/browserslist-config": "^2.3.0",
|
||||||
"@nextcloud/eslint-config": "^8.2.0",
|
"@nextcloud/eslint-config": "^8.2.0",
|
||||||
|
"@nextcloud/stylelint-config": "^2.3.0",
|
||||||
"@nextcloud/webpack-vue-config": "^5.4.0",
|
"@nextcloud/webpack-vue-config": "^5.4.0",
|
||||||
"cypress": "^11.2.0",
|
"cypress": "^11.2.0",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.3.1",
|
||||||
|
@ -100,4 +102,4 @@
|
||||||
"<rootDir>/node_modules/jest-serializer-vue"
|
"<rootDir>/node_modules/jest-serializer-vue"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Send title="" :size="22" decorative />
|
<Send title="" :size="22" decorative />
|
||||||
</template>
|
</template>
|
||||||
<template>{{ postTo }}</template>
|
{{ postTo }}
|
||||||
</NcButton>
|
</NcButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -669,8 +669,7 @@ export default {
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 2;
|
top: 2;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
<style>
|
|
||||||
/* Tribute-specific styles TODO: properly scope component css */
|
/* Tribute-specific styles TODO: properly scope component css */
|
||||||
.tribute-container {
|
.tribute-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -685,71 +684,72 @@ export default {
|
||||||
z-index: 999999;
|
z-index: 999999;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 1px 3px var(--color-box-shadow);
|
box-shadow: 0 1px 3px var(--color-box-shadow);
|
||||||
}
|
|
||||||
|
|
||||||
.tribute-container ul {
|
ul {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
background: var(--color-main-background);
|
background: var(--color-main-background);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tribute-container li {
|
li {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
|
||||||
|
|
||||||
.tribute-container li span {
|
span {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tribute-container li.highlight,
|
&.highlight,
|
||||||
.tribute-container li:hover {
|
&:hover {
|
||||||
background: var(--color-primary);
|
background: var(--color-primary);
|
||||||
color: var(--color-primary-text);
|
color: var(--color-primary-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tribute-container li img {
|
img {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-left: -3px;
|
margin-left: -3px;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tribute-container li span {
|
span {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tribute-container li.no-match {
|
&.no-match {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tribute-container .menu-highlighted {
|
}
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tribute-container .account,
|
.menu-highlighted {
|
||||||
.tribute-container li.highlight .account,
|
font-weight: bold;
|
||||||
.tribute-container li:hover .account {
|
}
|
||||||
font-weight: normal;
|
|
||||||
color: var(--color-text-light);
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tribute-container li.highlight .account,
|
.account,
|
||||||
.tribute-container li:hover .account {
|
li.highlight .account,
|
||||||
color: var(--color-primary-text) !important;
|
li:hover .account {
|
||||||
opacity: .6;
|
font-weight: normal;
|
||||||
|
color: var(--color-text-light);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.highlight .account,
|
||||||
|
li:hover .account {
|
||||||
|
color: var(--color-primary-text) !important;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message .mention {
|
.message .mention {
|
||||||
|
@ -760,15 +760,15 @@ export default {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
padding-bottom: 1px;
|
padding-bottom: 1px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
|
||||||
|
|
||||||
.mention img {
|
img {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hashtag {
|
.hashtag {
|
||||||
|
|
|
@ -22,18 +22,22 @@ export default {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
icon() {
|
icon() {
|
||||||
return twemoji.convert.toCodePoint(this.emoji.indexOf(U200D) < 0
|
return twemoji.convert.toCodePoint(this.emoji.indexOf(U200D) < 0
|
||||||
? this.emoji.replace(UFE0Fg, '')
|
? this.emoji.replace(UFE0Fg, '')
|
||||||
: this.emoji
|
: this.emoji
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
emojiUrl() {
|
emojiUrl() {
|
||||||
return generateFilePath('social', 'img', 'twemoji/' + this.icon + '.svg')
|
return generateFilePath('social', 'img', 'twemoji/' + this.icon + '.svg')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Emoji from './Emoji.vue'
|
import Emoji from './Emoji.vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} MessageSource
|
||||||
|
* @property {Array} tag
|
||||||
|
* @property {string} content
|
||||||
|
*/
|
||||||
|
|
||||||
export default Vue.component('MessageContent', {
|
export default Vue.component('MessageContent', {
|
||||||
props: {
|
props: {
|
||||||
source: {
|
source: {
|
||||||
|
@ -23,8 +29,8 @@ export default Vue.component('MessageContent', {
|
||||||
*
|
*
|
||||||
* All attributes other than `href` for links are stripped from the source
|
* All attributes other than `href` for links are stripped from the source
|
||||||
*
|
*
|
||||||
* @param createElement
|
* @param {Function} createElement
|
||||||
* @param source
|
* @param {MessageSource} source
|
||||||
*/
|
*/
|
||||||
export function formatMessage(createElement, source) {
|
export function formatMessage(createElement, source) {
|
||||||
if (!source.tag) {
|
if (!source.tag) {
|
||||||
|
@ -42,9 +48,9 @@ export function formatMessage(createElement, source) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param createElement
|
* @param {Function} createElement
|
||||||
* @param node
|
* @param {HTMLElement} node
|
||||||
* @param context
|
* @param {object} context
|
||||||
*/
|
*/
|
||||||
function domToVue(createElement, node, context) {
|
function domToVue(createElement, node, context) {
|
||||||
switch (node.tagName) {
|
switch (node.tagName) {
|
||||||
|
@ -55,9 +61,10 @@ function domToVue(createElement, node, context) {
|
||||||
case 'SPAN':
|
case 'SPAN':
|
||||||
return cleanCopy(createElement, node, context)
|
return cleanCopy(createElement, node, context)
|
||||||
case 'A':
|
case 'A':
|
||||||
|
// @ts-ignore - if tagName === 'A' then node is instance of HTMLLinkElement
|
||||||
return cleanLink(createElement, node, context)
|
return cleanLink(createElement, node, context)
|
||||||
default:
|
default:
|
||||||
return transformText(createElement, node.textContent)
|
return transformText(createElement, node.textContent ?? '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +73,8 @@ const hashTagRegex = /(\W|^)(#\w+)/i
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param createElement
|
* @param {Function} createElement
|
||||||
* @param text
|
* @param {string} text
|
||||||
*/
|
*/
|
||||||
function transformText(createElement, text) {
|
function transformText(createElement, text) {
|
||||||
return transformTextRegex(text, [
|
return transformTextRegex(text, [
|
||||||
|
@ -124,9 +131,9 @@ function transformText(createElement, text) {
|
||||||
/**
|
/**
|
||||||
* copy a node without any attributes and cleaning all children
|
* copy a node without any attributes and cleaning all children
|
||||||
*
|
*
|
||||||
* @param createElement
|
* @param {Function} createElement
|
||||||
* @param node
|
* @param {HTMLElement} node
|
||||||
* @param context
|
* @param {object} context
|
||||||
*/
|
*/
|
||||||
function cleanCopy(createElement, node, context) {
|
function cleanCopy(createElement, node, context) {
|
||||||
const children = Array.from(node.childNodes).map(node => domToVue(createElement, node, context))
|
const children = Array.from(node.childNodes).map(node => domToVue(createElement, node, context))
|
||||||
|
@ -135,17 +142,18 @@ function cleanCopy(createElement, node, context) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param createElement
|
* @param {Function} createElement
|
||||||
* @param node
|
* @param {HTMLLinkElement} node
|
||||||
* @param context
|
* @param {object} context
|
||||||
|
* @param {Array} context.mentions
|
||||||
*/
|
*/
|
||||||
function cleanLink(createElement, node, context) {
|
function cleanLink(createElement, node, context) {
|
||||||
const type = getLinkType(node.className)
|
const type = getLinkType(node.className)
|
||||||
const attributes = {}
|
const attributes = {}
|
||||||
|
const tag = matchMention(context.mentions, node.getAttribute('href') ?? '', node.textContent ?? '')
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'mention':
|
case 'mention':
|
||||||
var tag = matchMention(context.mentions, node.getAttribute('href'), node.textContent)
|
|
||||||
if (tag) {
|
if (tag) {
|
||||||
attributes.rel = 'nofollow noopener noreferrer'
|
attributes.rel = 'nofollow noopener noreferrer'
|
||||||
attributes.target = '_blank'
|
attributes.target = '_blank'
|
||||||
|
@ -163,7 +171,7 @@ function cleanLink(createElement, node, context) {
|
||||||
props: {
|
props: {
|
||||||
to: {
|
to: {
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
params: { tag: node.textContent.slice(1) },
|
params: { tag: node.textContent?.slice(1) },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -180,7 +188,7 @@ function cleanLink(createElement, node, context) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param className
|
* @param {string} className
|
||||||
*/
|
*/
|
||||||
function getLinkType(className) {
|
function getLinkType(className) {
|
||||||
const parts = className.split(' ')
|
const parts = className.split(' ')
|
||||||
|
@ -195,9 +203,9 @@ function getLinkType(className) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param tags
|
* @param {Array} tags
|
||||||
* @param mentionHref
|
* @param {string} mentionHref
|
||||||
* @param mentionText
|
* @param {string} mentionText
|
||||||
*/
|
*/
|
||||||
function matchMention(tags, mentionHref, mentionText) {
|
function matchMention(tags, mentionHref, mentionText) {
|
||||||
const mentionUrl = new URL(mentionHref)
|
const mentionUrl = new URL(mentionHref)
|
||||||
|
@ -225,8 +233,8 @@ const emojiRe = /(?:\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param text
|
* @param {string} text
|
||||||
* @param handlers
|
* @param {Array} handlers
|
||||||
*/
|
*/
|
||||||
function transformTextRegex(text, handlers) {
|
function transformTextRegex(text, handlers) {
|
||||||
const parts = []
|
const parts = []
|
||||||
|
|
|
@ -154,17 +154,17 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.list-item {
|
.list-enter-active, .list-leave-active {
|
||||||
}
|
transition: all .5s;
|
||||||
.list-enter-active, .list-leave-active {
|
}
|
||||||
transition: all .5s;
|
|
||||||
}
|
.list-enter {
|
||||||
.list-enter {
|
opacity: 0;
|
||||||
opacity: 0;
|
transform: translateY(-30px);
|
||||||
transform: translateY(-30px);
|
}
|
||||||
}
|
|
||||||
.list-leave-to {
|
.list-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-100px);
|
transform: translateX(-100px);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -91,7 +91,6 @@ import HeartOutline from 'vue-material-design-icons/HeartOutline.vue'
|
||||||
import logger from '../services/logger.js'
|
import logger from '../services/logger.js'
|
||||||
import moment from '@nextcloud/moment'
|
import moment from '@nextcloud/moment'
|
||||||
import { generateUrl } from '@nextcloud/router'
|
import { generateUrl } from '@nextcloud/router'
|
||||||
import RichText from '@nextcloud/vue-richtext'
|
|
||||||
import MessageContent from './MessageContent.js'
|
import MessageContent from './MessageContent.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -105,7 +104,6 @@ export default {
|
||||||
Reply,
|
Reply,
|
||||||
Heart,
|
Heart,
|
||||||
HeartOutline,
|
HeartOutline,
|
||||||
RichText,
|
|
||||||
MessageContent,
|
MessageContent,
|
||||||
},
|
},
|
||||||
mixins: [currentUser],
|
mixins: [currentUser],
|
||||||
|
@ -154,7 +152,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* @param e
|
* @param {MouseEvent} e - The click event
|
||||||
* @function getSinglePostTimeline
|
* @function getSinglePostTimeline
|
||||||
* @description Opens the timeline of the post clicked
|
* @description Opens the timeline of the post clicked
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/**
|
||||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @author Julius Härtl <jus@bitgrid.net>
|
* @author Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -20,11 +20,11 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Vue from 'vue'
|
import { nextTick } from 'vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
bind(el) {
|
bind(el) {
|
||||||
Vue.nextTick(() => {
|
nextTick(() => {
|
||||||
el.focus()
|
el.focus()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/**
|
||||||
* @copyright Copyright (c) 2019 Cyrille Bollu <cyrpub@bollu.be>
|
* @copyright Copyright (c) 2019 Cyrille Bollu <cyrpub@bollu.be>
|
||||||
*
|
*
|
||||||
* @author Cyrille Bollu <cyrpub@bollu.be>
|
* @author Cyrille Bollu <cyrpub@bollu.be>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* @file provides global account related methods
|
* @file provides global account related methods
|
||||||
*
|
*
|
||||||
|
@ -31,16 +31,18 @@ export default {
|
||||||
serverData,
|
serverData,
|
||||||
],
|
],
|
||||||
computed: {
|
computed: {
|
||||||
/** @function Returns the complete account name */
|
/** @return {string} the complete account name */
|
||||||
profileAccount() {
|
profileAccount() {
|
||||||
return (this.uid.indexOf('@') === -1) ? this.uid + '@' + this.hostname : this.uid
|
return (this.uid.indexOf('@') === -1) ? this.uid + '@' + this.hostname : this.uid
|
||||||
},
|
},
|
||||||
/** @functions Returns detailed information about an account (account must be loaded in the store first) */
|
|
||||||
|
/** @return detailed information about an account (account must be loaded in the store first) */
|
||||||
accountInfo() {
|
accountInfo() {
|
||||||
return this.$store.getters.getAccount(this.profileAccount)
|
return this.$store.getters.getAccount(this.profileAccount)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function Somewhat duplicate with accountInfo(), but needed (for some reason) to avoid glitches
|
* Somewhat duplicate with accountInfo(), but needed (for some reason) to avoid glitches
|
||||||
* where components would first show "user not found" before display an account's account info
|
* where components would first show "user not found" before display an account's account info
|
||||||
*/
|
*/
|
||||||
accountLoaded() {
|
accountLoaded() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/**
|
||||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @file Provides global methods for using the serverData structure.
|
* @file Provides global methods for using the serverData structure.
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* @author Julius Härtl <jus@bitgrid.net>
|
* @author Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -24,18 +24,22 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} ServerData
|
||||||
|
* @property {string} account - The account that the user wants to follow (Only in 'OStatus.vue')
|
||||||
|
* @property {string} cliUrl
|
||||||
|
* @property {string} cloudAddress
|
||||||
|
* @property {boolean} firstrun
|
||||||
|
* @property {boolean} isAdmin
|
||||||
|
* @property {string} local - The local part of the account that the user wants to follow
|
||||||
|
* @property {boolean} public - False when the page is accessed by an authenticated user. True otherwise
|
||||||
|
* @property setup
|
||||||
|
*/
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
/**
|
/**
|
||||||
* @description Returns the serverData object
|
* @return {Partial<ServerData>} Returns the serverData object
|
||||||
* @property {string} account - The account that the user wants to follow (Only in 'OStatus.vue')
|
|
||||||
* @property cliUrl
|
|
||||||
* @property cloudAddress
|
|
||||||
* @property firstrun
|
|
||||||
* @property isAdmin
|
|
||||||
* @property {string} local - The local part of the account that the user wants to follow
|
|
||||||
* @property {boolean} public - False when the page is accessed by an authenticated user. True otherwise
|
|
||||||
* @property setup
|
|
||||||
*/
|
*/
|
||||||
serverData() {
|
serverData() {
|
||||||
if (!this.$store) {
|
if (!this.$store) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* @copyright 2022 Carl Schwan <carl@carlschwan.eu>
|
* @copyright 2022 Carl Schwan <carl@carlschwan.eu>
|
||||||
* @license GNU AGPL version 3 or any later version
|
*
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* @author Julius Härtl <jus@bitgrid.net>
|
* @author Julius Härtl <jus@bitgrid.net>
|
||||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/**
|
||||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @author Julius Härtl <jus@bitgrid.net>
|
* @author Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import axios from '@nextcloud/axios'
|
import axios from '@nextcloud/axios'
|
||||||
import Vue from 'vue'
|
import { set } from 'vue'
|
||||||
import { generateUrl } from '@nextcloud/router'
|
import { generateUrl } from '@nextcloud/router'
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
|
@ -30,7 +30,7 @@ const state = {
|
||||||
accountIdMap: {},
|
accountIdMap: {},
|
||||||
}
|
}
|
||||||
const addAccount = (state, { actorId, data }) => {
|
const addAccount = (state, { actorId, data }) => {
|
||||||
Vue.set(state.accounts, actorId, Object.assign({
|
set(state.accounts, actorId, Object.assign({
|
||||||
followersList: [],
|
followersList: [],
|
||||||
followingList: [],
|
followingList: [],
|
||||||
details: {
|
details: {
|
||||||
|
@ -38,7 +38,7 @@ const addAccount = (state, { actorId, data }) => {
|
||||||
follower: false,
|
follower: false,
|
||||||
},
|
},
|
||||||
}, state.accounts[actorId], data))
|
}, state.accounts[actorId], data))
|
||||||
Vue.set(state.accountIdMap, data.account, data.id)
|
set(state.accountIdMap, data.account, data.id)
|
||||||
}
|
}
|
||||||
const _getActorIdForAccount = (account) => state.accountIdMap[account]
|
const _getActorIdForAccount = (account) => state.accountIdMap[account]
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ const mutations = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vue.set(state.accounts[_getActorIdForAccount(account)], 'followersList', users)
|
set(state.accounts[_getActorIdForAccount(account)], 'followersList', users)
|
||||||
},
|
},
|
||||||
addFollowing(state, { account, data }) {
|
addFollowing(state, { account, data }) {
|
||||||
const users = []
|
const users = []
|
||||||
|
@ -75,13 +75,13 @@ const mutations = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vue.set(state.accounts[_getActorIdForAccount(account)], 'followingList', users)
|
set(state.accounts[_getActorIdForAccount(account)], 'followingList', users)
|
||||||
},
|
},
|
||||||
followAccount(state, accountToFollow) {
|
followAccount(state, accountToFollow) {
|
||||||
Vue.set(state.accounts[_getActorIdForAccount(accountToFollow)].details, 'following', true)
|
set(state.accounts[_getActorIdForAccount(accountToFollow)].details, 'following', true)
|
||||||
},
|
},
|
||||||
unfollowAccount(state, accountToUnfollow) {
|
unfollowAccount(state, accountToUnfollow) {
|
||||||
Vue.set(state.accounts[_getActorIdForAccount(accountToUnfollow)].details, 'following', false)
|
set(state.accounts[_getActorIdForAccount(accountToUnfollow)].details, 'following', false)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/**
|
||||||
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
|
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
*
|
*
|
||||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||||
* @author Julius Härtl <jus@bitgrid.net>
|
* @author Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex, { Store } from 'vuex'
|
||||||
import timeline from './timeline.js'
|
import timeline from './timeline.js'
|
||||||
import account from './account.js'
|
import account from './account.js'
|
||||||
import settings from './settings.js'
|
import settings from './settings.js'
|
||||||
|
@ -31,7 +31,7 @@ Vue.use(Vuex)
|
||||||
|
|
||||||
const debug = process.env.NODE_ENV !== 'production'
|
const debug = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Store({
|
||||||
modules: {
|
modules: {
|
||||||
timeline,
|
timeline,
|
||||||
account,
|
account,
|
||||||
|
|
|
@ -36,6 +36,5 @@ const getters = {
|
||||||
return state.serverData
|
return state.serverData
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const actions = {}
|
|
||||||
|
|
||||||
export default { state, mutations, getters, actions }
|
export default { state, mutations, getters }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/**
|
||||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||||
*
|
*
|
||||||
* @file Timeline related store
|
* @file Timeline related store
|
||||||
|
@ -6,7 +6,7 @@
|
||||||
* @author Julius Härtl <jus@bitgrid.net>
|
* @author Julius Härtl <jus@bitgrid.net>
|
||||||
* @author Jonas Sulzer <jonas@violoncello.ch>
|
* @author Jonas Sulzer <jonas@violoncello.ch>
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -30,7 +30,7 @@ import { generateUrl } from '@nextcloud/router'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property {object} timeline - The posts' collection
|
* @property {object} timeline - The posts' collection
|
||||||
* @property {int} since - Time (EPOCH) of the most recent post
|
* @property {number} since - Time (EPOCH) of the most recent post
|
||||||
* @property {string} type - Timeline's type: 'home', 'single-post',...
|
* @property {string} type - Timeline's type: 'home', 'single-post',...
|
||||||
* @property {object} params - Timeline's parameters
|
* @property {object} params - Timeline's parameters
|
||||||
* @property {string} account -
|
* @property {string} account -
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
name="requesttoken"
|
name="requesttoken"
|
||||||
:value="OC.requestToken">
|
:value="OC.requestToken">
|
||||||
<div class="button-row">
|
<div class="button-row">
|
||||||
<NcButton type="primary" nativeType="submit">
|
<NcButton type="primary" native-type="submit">
|
||||||
{{ t('social', 'Authorize') }}
|
{{ t('social', 'Authorize') }}
|
||||||
</NcButton>
|
</NcButton>
|
||||||
<NcButton type="error" :href="homeUrl">
|
<NcButton type="error" :href="homeUrl">
|
||||||
|
|
|
@ -123,9 +123,11 @@ export default {
|
||||||
h2, p {
|
h2, p {
|
||||||
color: var(--color-primary-text);
|
color: var(--color-primary-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
p .icon {
|
p .icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatardiv {
|
.avatardiv {
|
||||||
vertical-align: -4px;
|
vertical-align: -4px;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
|
|
|
@ -68,6 +68,7 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-entry {
|
.user-entry {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
|
@ -40,7 +40,3 @@ export default {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div v-if="showInfo" class="social__welcome">
|
<div v-if="showInfo" class="social__welcome">
|
||||||
<a class="close icon-close" href="#" @click="hideInfo()">
|
<a class="close icon-close" href="#" @click="hideInfo()">
|
||||||
<span class="hidden-visually">
|
<span class="hidden-visually">
|
||||||
Close
|
{{ t('social', 'Close') }}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<h2>🎉 {{ t('social', 'Nextcloud becomes part of the federated social networks!') }}</h2>
|
<h2>🎉 {{ t('social', 'Nextcloud becomes part of the federated social networks!') }}</h2>
|
||||||
|
@ -149,6 +149,7 @@ export default {
|
||||||
transition: all .5s ease-out;
|
transition: all .5s ease-out;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slide-fade-leave-to {
|
.slide-fade-leave-to {
|
||||||
max-height: 0;
|
max-height: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -93,18 +93,12 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.social__timeline {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 15px auto;
|
||||||
|
}
|
||||||
|
|
||||||
.social__timeline {
|
#app-content {
|
||||||
max-width: 600px;
|
position: relative;
|
||||||
margin: 15px auto;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#app-content {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
const stylelintConfig = require('@nextcloud/stylelint-config')
|
||||||
|
|
||||||
|
module.exports = stylelintConfig
|
Ładowanie…
Reference in New Issue