Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pleroma/admin-fe
  • linafilippova/admin-fe
  • Exilat_a_Tolosa/admin-fe
  • mkljczk/admin-fe
  • maxf/admin-fe
  • kphrx/admin-fe
  • vaartis/admin-fe
  • ELR/admin-fe
  • eugenijm/admin-fe
  • jp/admin-fe
  • mkfain/admin-fe
  • lorenzoancora/admin-fe
  • alexgleason/admin-fe
  • seanking/admin-fe
  • ilja/admin-fe
15 results
Show changes
Showing
with 687 additions and 1374 deletions
// SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
// SPDX-License-Identifier: AGPL-3.0-only
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { baseName } from './utils'
......@@ -11,23 +14,23 @@ export async function fetchRelays(authHost, token) {
})
}
export async function addRelay(relay, authHost, token) {
export async function addRelay(relay_url, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/relay',
method: 'post',
headers: authHeaders(token),
data: { relay_url: relay }
data: { relay_url }
})
}
export async function deleteRelay(relay, authHost, token) {
export async function deleteRelay(relay_url, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/relay',
method: 'delete',
headers: authHeaders(token),
data: { relay_url: `https://${relay}/actor` }
data: { relay_url }
})
}
......
// SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
// SPDX-License-Identifier: AGPL-3.0-only
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { baseName } from './utils'
......@@ -24,10 +27,10 @@ export async function fetchReports(filter, page, pageSize, authHost, token) {
})
}
export async function fetchGroupedReports(authHost, token) {
export async function fetchSingleReport(id, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/grouped_reports`,
url: `/api/pleroma/admin/reports/${id}`,
method: 'get',
headers: authHeaders(token)
})
......
export const reports = [
{
id: '1',
timestamp: '2019/4/12',
local: true,
from: 'John', // actor nickname
object: 'Bob', // user nickname
header: 'Report #1', // content
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Nick', text: 'Lorem ipsum', id: '1', timestamp: '2019/4/13' },
{ author: 'Val', text: 'dolor sit amet', id: '2', timestamp: '2019/4/13' }
]
},
{
id: '2',
timestamp: '2019/4/1',
local: true,
from: 'Max',
object: 'Vic',
header: 'Report #2',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Tony', text: 'consectetur adipiscing elit', id: '3', timestamp: '2019/4/2' },
{ author: 'Zac', text: 'sed do eiusmod tempor incididunt', id: '4', timestamp: '2019/4/3' }
]
},
{
id: '3',
timestamp: '2019/2/28',
local: true,
from: 'Tim',
object: 'Jen',
header: 'Report #3',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [{ author: 'Bruce', text: 'ut labore et dolore magna aliqua', id: '5', timestamp: '2019/3/1' }]
},
{
id: '4',
timestamp: '2019/4/12',
local: true,
from: 'John', // actor nickname
object: 'Bob', // user nickname
header: 'Report #4', // content
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Nick', text: 'Lorem ipsum', id: '6', timestamp: '2019/4/13' },
{ author: 'Val', text: 'dolor sit amet', id: '7', timestamp: '2019/4/13' }
]
},
{
id: '5',
timestamp: '2019/4/1',
local: true,
from: 'Max',
object: 'Vic',
header: 'Report #5',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Tony', text: 'consectetur adipiscing elit', id: '8', timestamp: '2019/4/2' },
{ author: 'Zac', text: 'sed do eiusmod tempor incididunt', id: '9', timestamp: '2019/4/3' }
]
},
{
id: '6',
timestamp: '2019/2/28',
local: true,
from: 'Tim',
object: 'Jen',
header: 'Report #6',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [{ author: 'Bruce', text: 'ut labore et dolore magna aliqua', id: '10', timestamp: '2019/3/1' }]
},
{
id: '7',
timestamp: '2019/4/12',
local: true,
from: 'John', // actor nickname
object: 'Bob', // user nickname
header: 'Report #7', // content
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Nick', text: 'Lorem ipsum', id: '11', timestamp: '2019/4/13' },
{ author: 'Val', text: 'dolor sit amet', id: '12', timestamp: '2019/4/13' }
]
},
{
id: '8',
timestamp: '2019/4/1',
local: true,
from: 'Max',
object: 'Vic',
header: 'Report #8',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Tony', text: 'consectetur adipiscing elit', id: '13', timestamp: '2019/4/2' },
{ author: 'Zac', text: 'sed do eiusmod tempor incididunt', id: '14', timestamp: '2019/4/3' }
]
},
{
id: '9',
timestamp: '2019/2/28',
local: true,
from: 'Tim',
object: 'Jen',
header: 'Report #9',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [{ author: 'Bruce', text: 'ut labore et dolore magna aliqua', id: '15', timestamp: '2019/3/1' }]
},
{
id: '10',
timestamp: '2019/4/12',
local: true,
from: 'John', // actor nickname
object: 'Bob', // user nickname
header: 'Report #10', // content
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Nick', text: 'Lorem ipsum', id: '16', timestamp: '2019/4/13' },
{ author: 'Val', text: 'dolor sit amet', id: '17', timestamp: '2019/4/13' }
]
},
{
id: '11',
timestamp: '2019/4/1',
local: true,
from: 'Max',
object: 'Vic',
header: 'Report #11',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Tony', text: 'consectetur adipiscing elit', id: '18', timestamp: '2019/4/2' },
{ author: 'Zac', text: 'sed do eiusmod tempor incididunt', id: '19', timestamp: '2019/4/3' }
]
},
{
id: '12',
timestamp: '2019/2/28',
local: true,
from: 'Tim',
object: 'Jen',
header: 'Report #12',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [{ author: 'Bruce', text: 'ut labore et dolore magna aliqua', id: '20', timestamp: '2019/3/1' }]
},
{
id: '13',
timestamp: '2019/4/12',
local: true,
from: 'John', // actor nickname
object: 'Bob', // user nickname
header: 'Report #13', // content
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Nick', text: 'Lorem ipsum', id: '21', timestamp: '2019/4/13' },
{ author: 'Val', text: 'dolor sit amet', id: '22', timestamp: '2019/4/13' }
]
},
{
id: '14',
timestamp: '2019/4/1',
local: true,
from: 'Max',
object: 'Vic',
header: 'Report #14',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Tony', text: 'consectetur adipiscing elit', id: '23', timestamp: '2019/4/2' },
{ author: 'Zac', text: 'sed do eiusmod tempor incididunt', id: '24', timestamp: '2019/4/3' }
]
},
{
id: '15',
timestamp: '2019/2/28',
local: true,
from: 'Tim',
object: 'Jen',
header: 'Report #15',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [{ author: 'Bruce', text: 'ut labore et dolore magna aliqua', id: '25', timestamp: '2019/3/1' }]
},
{
id: '16',
timestamp: '2019/4/12',
local: true,
from: 'John', // actor nickname
object: 'Bob', // user nickname
header: 'Report #16', // content
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Nick', text: 'Lorem ipsum', id: '26', timestamp: '2019/4/13' },
{ author: 'Val', text: 'dolor sit amet', id: '27', timestamp: '2019/4/13' }
]
},
{
id: '17',
timestamp: '2019/4/1',
local: true,
from: 'Max',
object: 'Vic',
header: 'Report #17',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [
{ author: 'Tony', text: 'consectetur adipiscing elit', id: '28', timestamp: '2019/4/2' },
{ author: 'Zac', text: 'sed do eiusmod tempor incididunt', id: '29', timestamp: '2019/4/3' }
]
},
{
id: '18',
timestamp: '2019/2/28',
local: true,
from: 'Tim',
object: 'Jen',
header: 'Report #18',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
notes: [{ author: 'Bruce', text: 'ut labore et dolore magna aliqua', id: '30', timestamp: '2019/3/1' }]
}
]
// SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
// SPDX-License-Identifier: AGPL-3.0-only
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { baseName } from './utils'
import _ from 'lodash'
export async function deleteInstanceDocument(name, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/instance_document/${name}`,
method: 'delete',
headers: authHeaders(token)
})
}
export async function fetchDescription(authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/v1/pleroma/admin/config/descriptions`,
method: 'get',
headers: authHeaders(token)
})
}
export async function fetchDescription2(authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/v2/pleroma/admin/config/descriptions`,
method: 'get',
headers: authHeaders(token)
})
}
export async function fetchSettings(authHost, token) {
return await request({
......@@ -11,6 +42,25 @@ export async function fetchSettings(authHost, token) {
})
}
export async function getInstanceDocument(name, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/instance_document/${name}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function updateInstanceDocument(name, formData, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/instance_document/${name}`,
method: 'patch',
data: formData,
headers: { ...authHeaders(token), 'Content-Type': 'multipart/form-data' }
})
}
export async function updateSettings(configs, authHost, token) {
return await request({
baseURL: baseName(authHost),
......@@ -21,15 +71,33 @@ export async function updateSettings(configs, authHost, token) {
})
}
export async function uploadMedia(file, authHost, token) {
const formData = new FormData()
formData.append('file', file)
export async function removeSettings(configs, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/config`,
method: 'post',
headers: authHeaders(token),
data: { configs }
})
}
export async function fetchFrontends(authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/frontends`,
method: 'get',
headers: authHeaders(token)
})
}
export async function installFrontend(data, authHost, token) {
const filteredData = _.pickBy(data)
return await request({
baseURL: baseName(authHost),
url: `/api/v1/media`,
url: `/api/pleroma/admin/frontends/install`,
method: 'post',
headers: authHeaders(token),
data: formData
data: filteredData
})
}
......
// SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
// SPDX-License-Identifier: AGPL-3.0-only
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { baseName } from './utils'
......@@ -21,7 +24,34 @@ export async function deleteStatus(id, authHost, token) {
})
}
export async function fetchStatusesByInstance(instance, authHost, token, pageSize, page = 1) {
export async function fetchStatus(id, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/statuses/${id}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function fetchStatuses({ godmode, localOnly, authHost, token, pageSize, page }) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/statuses?godmode=${godmode}&local_only=${localOnly}&page=${page}&page_size=${pageSize}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function fetchStatusesCount(instance, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: instance ? `/api/pleroma/admin/stats?instance=${instance}` : `/api/pleroma/admin/stats`,
method: 'get',
headers: authHeaders(token)
})
}
export async function fetchStatusesByInstance({ instance, authHost, token, pageSize, page }) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/instances/${instance}/statuses?page=${page}&page_size=${pageSize}`,
......
// SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
// SPDX-License-Identifier: AGPL-3.0-only
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { baseName } from './utils'
......@@ -62,6 +65,16 @@ export async function deleteUsers(nicknames, authHost, token) {
})
}
export async function disableMfa(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/disable_mfa`,
method: 'put',
headers: authHeaders(token),
data: { nickname }
})
}
export async function fetchUser(id, authHost, token) {
return await request({
baseURL: baseName(authHost),
......@@ -71,10 +84,36 @@ export async function fetchUser(id, authHost, token) {
})
}
export async function fetchUsers(filters, authHost, token, page = 1) {
export async function fetchUserCredentials(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/credentials`,
method: 'get',
headers: authHeaders(token)
})
}
export async function updateUserCredentials(nickname, credentials, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/credentials`,
method: 'patch',
headers: authHeaders(token),
data: credentials
})
}
export async function fetchUsers(filters, actorTypeFilters, authHost, token, page = 1) {
const url = actorTypeFilters.length === 0
? `/api/pleroma/admin/users?page=${page}&filters=${filters}`
: actorTypeFilters.reduce((acc, filter) => {
const newAcc = acc.concat(`&actor_types[]=${filter}`)
return newAcc
}, `/api/pleroma/admin/users?page=${page}&filters=${filters}`)
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users?page=${page}&filters=${filters}`,
url,
method: 'get',
headers: authHeaders(token)
})
......@@ -89,19 +128,27 @@ export async function getPasswordResetToken(nickname, authHost, token) {
})
}
export async function requirePasswordReset(nickname, authHost, token) {
export async function forcePasswordReset(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/force_password_reset`,
url: `/api/pleroma/admin/users/force_password_reset`,
method: 'patch',
headers: authHeaders(token)
headers: authHeaders(token),
data: { nicknames }
})
}
export async function searchUsers(query, filters, authHost, token, page = 1) {
export async function searchUsers(query, filters, actorTypeFilters, authHost, token, page = 1) {
const url = actorTypeFilters.length === 0
? `/api/pleroma/admin/users?query=${query}&page=${page}&filters=${filters}`
: actorTypeFilters.reduce((acc, filter) => {
const newAcc = acc.concat(`&actor_types[]=${filter}`)
return newAcc
}, `/api/pleroma/admin/users?query=${query}&page=${page}&filters=${filters}`)
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users?query=${query}&page=${page}&filters=${filters}`,
url,
method: 'get',
headers: authHeaders(token)
})
......@@ -136,6 +183,25 @@ export async function fetchUserStatuses(id, authHost, godmode, token) {
})
}
export async function fetchUserChats(id, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${id}/chats`,
method: 'get',
headers: authHeaders(token)
})
}
export async function approveUserAccount(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/approve',
method: 'patch',
headers: authHeaders(token),
data: { nicknames }
})
}
export async function confirmUserEmail(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
......
// SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
// SPDX-License-Identifier: AGPL-3.0-only
const isLocalhost = (instanceName) =>
instanceName.startsWith('localhost:') || instanceName.startsWith('127.0.0.1:')
......
src/assets/404_images/404.png

95.8 KiB

src/assets/404_images/404_cloud.png

4.65 KiB

This diff is collapsed.
<!--
SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<el-card v-if="!message.deleted" class="message-card">
<div slot="header">
<div class="message-header">
<div class="message-meta">
<router-link
v-if="propertyExists(author, 'id')"
:to="{ name: 'UsersShow', params: { id: author.id }}"
class="router-link"
@click.native.stop>
<div class="message-author">
<img v-if="propertyExists(author, 'avatar')" :src="author.avatar" class="message-author-avatar-img">
<span v-if="propertyExists(author, 'username')" class="message-author-name">{{ author.username }}</span>
<span v-else>
<span v-if="propertyExists(author, 'username')" class="message-author-name">
{{ author.username }}
</span>
<span v-else class="message-author-name deactivated">({{ $t('users.invalidNickname') }})</span>
</span>
</div>
</router-link>
<span class="message-timestamp">{{ parseTimestamp(message.created_at) }}</span>
</div>
<div class="message-actions">
<el-dropdown trigger="click" @click.native.stop>
<el-button plain size="small" icon="el-icon-edit" class="status-actions-button">
{{ $t('reports.messageModeration') }}<i class="el-icon-arrow-down el-icon--right"/>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
@click.native="deleteMessage()">
{{ $t('reports.deleteMessage') }}
</el-dropdown-item>
<el-dropdown-item
@click.native="handleRouteChange()">
{{ $t('users.moderateUser') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
<div class="message-body">
<span class="message-content" v-html="message.content"/>
<div v-if="message.attachment" class="image">
<img :src="message.attachment.preview_url">
</div>
</div>
</el-card>
</template>
<script>
import { DateTime } from 'luxon'
export default {
name: 'ChatMessage',
props: {
message: {
type: Object,
required: true
},
author: {
type: Object,
required: true
},
page: {
type: Number,
required: false,
default: 0
}
},
data() {
return {
}
},
methods: {
propertyExists(account, property) {
return account[property]
},
parseTimestamp(timestamp) {
return DateTime.fromISO(timestamp).toFormat('yyyy-MM-dd HH:mm')
},
deleteMessage() {
this.$confirm('Are you sure you want to delete this message?', 'Warning', {
confirmButtonText: 'OK',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
this.$store.dispatch('DeleteMessage', {
chat_id: this.message.chat_id,
message_id: this.message.id
})
this.$message({
type: 'success',
message: 'Delete completed'
})
}).catch(() => {
this.$message({
type: 'info',
message: 'Delete canceled'
})
})
},
handleRouteChange() {
this.$router.push({ name: 'UsersShow', params: { id: this.author.id }})
}
}
}
</script>
<style rel='stylesheet/scss' lang='scss'>
.message-card {
margin-bottom: 10px;
.account {
line-height: 26px;
font-size: 13px;
color: #606266;
}
.account:hover {
text-decoration: underline;
}
.deactivated {
color: gray;
line-height: 28px;
vertical-align: middle;
}
.image {
width: 20%;
img {
width: 100%;
}
}
.router-link {
text-decoration: none;
}
.show-more-button {
margin-left: 5px;
}
.message-author {
display: flex;
align-items: center;
}
.message-author-avatar-img {
display: inline-block;
width: 15px;
height: 15px;
margin-right: 5px;
}
.message-author-name {
display: inline-block;
margin: 0;
font-size: 15px;
font-weight: 500;
}
.message-body {
display: flex;
flex-direction: column;
}
.message-card-header {
display: flex;
align-items: center;
}
.chat-content {
font-size: 15px;
line-height: 26px;
}
.message-timestamp {
font-size: 13px;
color: #606266;
margin-left: 20px;
}
.message-deleted {
font-style: italic;
margin-top: 3px;
}
.message-header {
display: flex;
justify-content: space-between;
align-items: center;
.message-meta {
display: flex;
justify-content: flex-start;
align-items: flex-end;
}
}
}
@media only screen and (max-width:480px) {
.el-message {
min-width: 80%;
}
.el-message-box {
width: 80%;
}
.message-card {
.el-card__header {
padding: 10px 17px;
}
.el-tag {
margin: 3px 0;
}
.message-author-container {
margin-bottom: 5px;
}
.message-action-buttons {
margin: 3px 0 3px;
}
.message-actions {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.message-header {
display: flex;
flex-direction: column;
align-items: flex-start;
}
}
.message-actions-button {
margin: 3px 0 3px;
}
.message-actions {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
}
</style>
<!--
SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<el-tooltip v-if="needReboot" :content="$t('settings.restartApp')" placement="bottom-end">
<el-button type="warning" class="reboot-button" @click="restartApp">
<span>
<i class="el-icon-refresh"/>
{{ $t('settings.instanceReboot') }}
</span>
</el-button>
</el-tooltip>
</template>
<script>
import i18n from '@/lang'
export default {
name: 'RebootButton',
computed: {
needReboot() {
return this.$store.state.app.needReboot
}
},
methods: {
async restartApp() {
try {
await this.$store.dispatch('RestartApplication')
} catch (e) {
return
}
this.$message({
type: 'success',
message: i18n.t('settings.restartSuccess')
})
}
}
}
</script>
<!--
SPDX-FileCopyrightText: 2019-2022 Pleroma Authors <https://pleroma.social>
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div>
<el-card v-if="!status.deleted" class="status-card">
<div slot="header">
<div class="status-header">
<div class="status-account-container">
<div class="status-account">
<el-checkbox @change="handleStatusSelection(status.account)">
<img :src="status.account.avatar" class="status-avatar-img">
<h3 class="status-account-name">{{ status.account.display_name }}</h3>
</el-checkbox>
</div>
<a :href="status.account.url" target="_blank" class="account">
@{{ status.account.acct }}
</a>
<el-card v-if="!status.deleted" class="status-card" @click.native="handleRouteChange()">
<div slot="header">
<div class="status-header">
<div class="status-account-container">
<div class="status-account">
<el-checkbox v-if="showCheckbox" class="status-checkbox" @change="handleStatusSelection(account)"/>
<router-link
v-if="propertyExists(account, 'id')"
:to="{ name: 'UsersShow', params: { id: account.id }}"
class="router-link"
@click.native.stop>
<div class="status-card-header">
<img v-if="propertyExists(account, 'avatar')" :src="account.avatar" class="status-avatar-img">
<span v-if="propertyExists(account, 'nickname')" class="status-account-name">{{ account.nickname }}</span>
<span v-else>
<span v-if="propertyExists(account, 'nickname')" class="status-account-name">
{{ account.nickname }}
</span>
<span v-else class="status-account-name deactivated">({{ $t('users.invalidNickname') }})</span>
</span>
</div>
</router-link>
</div>
<div class="status-actions">
</div>
<div v-if="isPrivileged(['messages_delete'], [])" class="status-actions">
<div class="status-tags">
<el-tag v-if="status.sensitive" type="warning" size="large">{{ $t('reports.sensitive') }}</el-tag>
<el-tag size="large">{{ capitalizeFirstLetter(status.visibility) }}</el-tag>
<el-dropdown trigger="click">
<el-button plain size="small" icon="el-icon-edit" class="status-actions-button">
{{ $t('reports.changeScope') }}<i class="el-icon-arrow-down el-icon--right"/>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-if="!status.sensitive"
@click.native="changeStatus(status.id, true, status.visibility)">
{{ $t('reports.addSensitive') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.sensitive"
@click.native="changeStatus(status.id, false, status.visibility)">
{{ $t('reports.removeSensitive') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.visibility !== 'public'"
@click.native="changeStatus(status.id, status.sensitive, 'public')">
{{ $t('reports.public') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.visibility !== 'private'"
@click.native="changeStatus(status.id, status.sensitive, 'private')">
{{ $t('reports.private') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.visibility !== 'unlisted'"
@click.native="changeStatus(status.id, status.sensitive, 'unlisted')">
{{ $t('reports.unlisted') }}
</el-dropdown-item>
<el-dropdown-item
@click.native="deleteStatus(status.id)">
{{ $t('reports.deleteStatus') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<el-dropdown trigger="click" @click.native.stop>
<el-button plain size="small" icon="el-icon-edit" class="status-actions-button">
{{ $t('reports.changeScope') }}<i class="el-icon-arrow-down el-icon--right"/>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-if="!status.sensitive"
@click.native="changeStatus(status.id, true, status.visibility)">
{{ $t('reports.addSensitive') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.sensitive"
@click.native="changeStatus(status.id, false, status.visibility)">
{{ $t('reports.removeSensitive') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.visibility !== 'public'"
@click.native="changeStatus(status.id, status.sensitive, 'public')">
{{ $t('reports.public') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.visibility !== 'private'"
@click.native="changeStatus(status.id, status.sensitive, 'private')">
{{ $t('reports.private') }}
</el-dropdown-item>
<el-dropdown-item
v-if="status.visibility !== 'unlisted'"
@click.native="changeStatus(status.id, status.sensitive, 'unlisted')">
{{ $t('reports.unlisted') }}
</el-dropdown-item>
<el-dropdown-item
@click.native="deleteStatus(status.id)">
{{ $t('reports.deleteStatus') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
<div class="status-body">
<div v-if="status.spoiler_text">
<strong>{{ status.spoiler_text }}</strong>
<el-button v-if="!showHiddenStatus" size="mini" class="show-more-button" @click="showHiddenStatus = true">Show more</el-button>
<el-button v-if="showHiddenStatus" size="mini" class="show-more-button" @click="showHiddenStatus = false">Show less</el-button>
<div v-if="showHiddenStatus">
<span class="status-content" v-html="status.content"/>
<div v-if="status.poll" class="poll">
<ul>
<li v-for="(option, index) in status.poll.options" :key="index">
{{ option.title }}
<el-progress :percentage="optionPercent(status.poll, option)" />
</li>
</ul>
</div>
<div v-for="(attachment, index) in status.media_attachments" :key="index" class="image">
<img :src="attachment.preview_url">
</div>
</div>
</div>
<div v-if="!status.spoiler_text">
</div>
<div class="status-body">
<div v-if="status.spoiler_text">
<strong>{{ status.spoiler_text }}</strong>
<el-button v-if="!showHiddenStatus" size="mini" class="show-more-button" @click="showHiddenStatus = true">Show more</el-button>
<el-button v-if="showHiddenStatus" size="mini" class="show-more-button" @click="showHiddenStatus = false">Show less</el-button>
<div v-if="showHiddenStatus">
<span class="status-content" v-html="status.content"/>
<div v-if="status.poll" class="poll">
<ul>
......@@ -90,38 +91,74 @@
<img :src="attachment.preview_url">
</div>
</div>
<a :href="status.url" target="_blank" class="account">
{{ parseTimestamp(status.created_at) }}
</div>
<div v-if="!status.spoiler_text">
<span class="status-content" v-html="status.content"/>
<div v-if="status.poll" class="poll">
<ul>
<li v-for="(option, index) in status.poll.options" :key="index">
{{ option.title }}
<el-progress :percentage="optionPercent(status.poll, option)" />
</li>
</ul>
</div>
<div v-for="(attachment, index) in status.media_attachments" :key="index" class="image">
<img :src="attachment.preview_url">
</div>
</div>
<div class="status-footer">
<span class="status-created-at">{{ parseTimestamp(status.created_at) }}</span>
<a v-if="status.url" :href="status.url" target="_blank" class="account" @click.stop>
{{ $t('statuses.openStatusInInstance') }}
<i class="el-icon-top-right"/>
</a>
</div>
</el-card>
<el-card v-else class="status-card">
<div slot="header">
<div class="status-header">
<div class="status-account-container">
<div class="status-account">
<h4 class="status-deleted">{{ $t('reports.statusDeleted') }}</h4>
</div>
</div>
</el-card>
<el-card v-else class="status-card">
<div slot="header">
<div class="status-header">
<div class="status-account-container">
<div class="status-account">
<h4 class="status-deleted">{{ $t('reports.statusDeleted') }}</h4>
</div>
</div>
</div>
<div class="status-body">
<span v-if="status.content" class="status-content" v-html="status.content"/>
<span v-else class="status-without-content">no content</span>
</div>
<a v-if="status.created_at" :href="status.url" target="_blank" class="account">
{{ parseTimestamp(status.created_at) }}
</div>
<div class="status-body">
<span v-if="status.content" class="status-content" v-html="status.content"/>
<span v-else class="status-without-content">no content</span>
</div>
<div class="status-footer">
<span v-if="status.created_at" class="status-created-at">{{ parseTimestamp(status.created_at) }}</span>
<a v-if="status.url" :href="status.url" target="_blank" class="account" @click.stop>
Open status in instance
<i class="el-icon-top-right"/>
</a>
</el-card>
</div>
</div>
</el-card>
</template>
<script>
import moment from 'moment'
import { DateTime } from 'luxon'
export default {
name: 'Status',
props: {
account: {
type: Object,
required: false,
default: () => { return {} }
},
fetchStatusesByInstance: {
type: Boolean,
required: false,
default: false
},
showCheckbox: {
type: Boolean,
required: true,
default: false
},
status: {
type: Object,
required: true
......@@ -151,8 +188,21 @@ export default {
capitalizeFirstLetter(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
},
isPrivileged(accepted_privileges, accepted_roles) {
const user_privileges = this.$store.getters.privileges
const user_roles = this.$store.getters.roles
return accepted_privileges.some(privilege => user_privileges.indexOf(privilege) >= 0) || accepted_roles.some(role => user_roles.indexOf(role) >= 0)
},
changeStatus(statusId, isSensitive, visibility) {
this.$store.dispatch('ChangeStatusScope', { statusId, isSensitive, visibility, reportCurrentPage: this.page, userId: this.userId, godmode: this.godmode })
this.$store.dispatch('ChangeStatusScope', {
statusId,
isSensitive,
visibility,
reportCurrentPage: this.page,
userId: this.userId,
godmode: this.godmode,
fetchStatusesByInstance: this.fetchStatusesByInstance
})
},
deleteStatus(statusId) {
this.$confirm('Are you sure you want to delete this status?', 'Warning', {
......@@ -160,7 +210,13 @@ export default {
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
this.$store.dispatch('DeleteStatus', { statusId, reportCurrentPage: this.page, userId: this.userId, godmode: this.godmode })
this.$store.dispatch('DeleteStatus', {
statusId,
reportCurrentPage: this.page,
userId: this.userId,
godmode: this.godmode,
fetchStatusesByInstance: this.fetchStatusesByInstance
})
this.$message({
type: 'success',
message: 'Delete completed'
......@@ -172,6 +228,12 @@ export default {
})
})
},
handleStatusSelection(account) {
this.$emit('status-selection', account)
},
handleRouteChange() {
this.$router.push({ name: 'StatusShow', params: { id: this.status.id }})
},
optionPercent(poll, pollOption) {
const allVotes = poll.options.reduce((acc, option) => (acc + option.votes_count), 0)
if (allVotes === 0) {
......@@ -180,10 +242,13 @@ export default {
return +(pollOption.votes_count / allVotes * 100).toFixed(1)
},
parseTimestamp(timestamp) {
return moment(timestamp).format('YYYY-MM-DD HH:mm')
return DateTime.fromISO(timestamp).toFormat('yyyy-MM-dd HH:mm')
},
handleStatusSelection(account) {
this.$emit('status-selection', account)
propertyExists(account, property, _secondProperty) {
if (_secondProperty) {
return account[property] && account[_secondProperty]
}
return account[property]
}
}
}
......@@ -191,10 +256,20 @@ export default {
<style rel='stylesheet/scss' lang='scss'>
.status-card {
margin-bottom: 10px;
cursor: pointer;
.account {
text-decoration: underline;
line-height: 26px;
font-size: 13px;
color: #606266;
}
.account:hover {
text-decoration: underline;
}
.deactivated {
color: gray;
line-height: 28px;
vertical-align: middle;
}
.image {
width: 20%;
......@@ -202,6 +277,9 @@ export default {
width: 100%;
}
}
.router-link {
text-decoration: none;
}
.show-more-button {
margin-left: 5px;
}
......@@ -218,34 +296,51 @@ export default {
.status-account-name {
display: inline-block;
margin: 0;
height: 22px;
font-size: 15px;
font-weight: 500;
}
.status-body {
display: flex;
flex-direction: column;
}
.status-card-header {
display: flex;
align-items: center;
}
.status-checkbox {
margin-right: 7px;
}
.status-content {
font-size: 15px;
line-height: 26px;
}
.status-card {
margin-bottom: 15px;
.status-created-at {
font-size: 13px;
color: #606266;
}
.status-deleted {
font-style: italic;
margin-top: 3px;
}
.status-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.status-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.status-tags {
display: inline;
}
.status-without-content {
font-style: italic;
}
}
@media
only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-width: 1024px) {
@media only screen and (max-width:480px) {
.el-message {
min-width: 80%;
}
......@@ -257,7 +352,7 @@ only screen and (max-width: 760px),
padding: 10px 17px;
}
.el-tag {
margin: 3px 4px 3px 0;
margin: 3px 0;
}
.status-account-container {
margin-bottom: 5px;
......@@ -266,12 +361,20 @@ only screen and (max-width: 760px),
margin: 3px 0 3px;
}
.status-actions {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.status-footer {
flex-direction: column;
align-items: flex-start;
margin-top: 10px;
}
.status-header {
display: flex;
flex-direction: column;
align-items: flex-start;
}
}
}
......
<template>
<transition :name="transitionName">
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
<svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height: 16px; width: 16px;">
<title>回到顶部</title>
<g>
<path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd"/>
</g>
</svg>
</div>
</transition>
</template>
<script>
export default {
name: 'BackToTop',
props: {
visibilityHeight: {
type: Number,
default: 400
},
backPosition: {
type: Number,
default: 0
},
customStyle: {
type: Object,
default: function() {
return {
right: '50px',
bottom: '50px',
width: '40px',
height: '40px',
'border-radius': '4px',
'line-height': '45px',
background: '#e7eaf1'
}
}
},
transitionName: {
type: String,
default: 'fade'
}
},
data: function() {
return {
visible: false,
interval: null,
isMoving: false
}
},
mounted() {
window.addEventListener('scroll', this.handleScroll)
},
beforeDestroy() {
window.removeEventListener('scroll', this.handleScroll)
if (this.interval) {
clearInterval(this.interval)
}
},
methods: {
handleScroll() {
this.visible = window.pageYOffset > this.visibilityHeight
},
backToTop() {
if (this.isMoving) return
const start = window.pageYOffset
let i = 0
this.isMoving = true
this.interval = setInterval(() => {
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
if (next <= this.backPosition) {
window.scrollTo(0, this.backPosition)
clearInterval(this.interval)
this.isMoving = false
} else {
window.scrollTo(0, next)
}
i++
}, 16.7)
},
easeInOutQuad(t, b, c, d) {
if ((t /= d / 2) < 1) return c / 2 * t * t + b
return -c / 2 * (--t * (t - 2) - 1) + b
}
}
}
</script>
<style scoped>
.back-to-ceiling {
position: fixed;
display: inline-block;
text-align: center;
cursor: pointer;
}
.back-to-ceiling:hover {
background: #d5dbe7;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0
}
.back-to-ceiling .Icon {
fill: #9aaabf;
background: none;
}
</style>
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{
generateTitle(item.meta.title) }}</span>
<a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import { generateTitle } from '@/utils/i18n'
import pathToRegexp from 'path-to-regexp'
export default {
data: function() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
generateTitle,
getBreadcrumb() {
let matched = this.$route.matched.filter(item => item.name)
const first = matched[0]
if (first && first.name.trim().toLocaleLowerCase() !== 'Dashboard'.toLocaleLowerCase()) {
matched = [{ path: '/dashboard', meta: { title: 'dashboard' }}].concat(matched)
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.