diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
index 3b946b4b..3c8975e3 100644
--- a/build/webpack.base.conf.js
+++ b/build/webpack.base.conf.js
@@ -83,9 +83,8 @@ module.exports = {
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
- loader: 'url-loader',
+ loader: 'file-loader',
options: {
- limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
diff --git a/build/webpack.dev.conf.js b/build/webpack.dev.conf.js
index 5df16341..fb90173a 100644
--- a/build/webpack.dev.conf.js
+++ b/build/webpack.dev.conf.js
@@ -16,6 +16,8 @@ function resolve(dir) {
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
+const devEnv = require('../config/dev.env')
+
const devWebpackConfig = merge(baseWebpackConfig, {
mode: 'development',
module: {
@@ -39,11 +41,14 @@ const devWebpackConfig = merge(baseWebpackConfig, {
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
- publicPath: config.dev.assetsPublicPath,
+ publicPath: devEnv.ASSETS_PUBLIC_PATH,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll
+ },
+ headers: {
+ 'content-security-policy': "base-uri 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; manifest-src 'self'; script-src 'self';"
}
},
plugins: [
@@ -59,7 +64,7 @@ const devWebpackConfig = merge(baseWebpackConfig, {
favicon: resolve('favicon.ico'),
title: 'Admin FE',
templateParameters: {
- BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory,
+ BASE_URL: devEnv.ASSETS_PUBLIC_PATH + config.dev.assetsSubDirectory,
},
}),
]
diff --git a/build/webpack.prod.conf.js b/build/webpack.prod.conf.js
index 5e991636..7f2cdda7 100644
--- a/build/webpack.prod.conf.js
+++ b/build/webpack.prod.conf.js
@@ -57,7 +57,7 @@ const webpackConfig = merge(baseWebpackConfig, {
favicon: resolve('favicon.ico'),
title: 'Admin FE',
templateParameters: {
- BASE_URL: config.build.assetsPublicPath + config.build.assetsSubDirectory,
+ BASE_URL: env.ASSETS_PUBLIC_PATH + config.build.assetsSubDirectory,
},
minify: {
removeComments: true,
@@ -70,10 +70,6 @@ const webpackConfig = merge(baseWebpackConfig, {
// in certain cases, and in webpack 4, chunk order in HTML doesn't
// matter anyway
}),
- new ScriptExtHtmlWebpackPlugin({
- //`runtime` must same as runtimeChunk name. default is `runtime`
- inline: /runtime\..*\.js$/
- }),
// keep chunk.id stable when chunk has no name
new webpack.NamedChunksPlugin(chunk => {
if (chunk.name) {
diff --git a/config/dev.env.js b/config/dev.env.js
index f2b2a130..6704d298 100644
--- a/config/dev.env.js
+++ b/config/dev.env.js
@@ -1,4 +1,5 @@
module.exports = {
NODE_ENV: '"development"',
- ENV_CONFIG: '"dev"'
+ ENV_CONFIG: '"dev"',
+ ASSETS_PUBLIC_PATH: '/'
}
diff --git a/config/index.js b/config/index.js
index 599e4a63..7043ee18 100644
--- a/config/index.js
+++ b/config/index.js
@@ -8,7 +8,7 @@ module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
- assetsPublicPath: '/',
+ // assetsPublicPath: '', // To configure assetsPublicPath set ASSETS_PUBLIC_PATH in dev/prod.env.js
proxyTable: {},
// Various Dev Server settings
@@ -60,7 +60,7 @@ module.exports = {
* then assetsPublicPath should be set to "/bar/".
* In most cases please use '/' !!!
*/
- assetsPublicPath: '/',
+ // assetsPublicPath: '', // To configure assetsPublicPath set ASSETS_PUBLIC_PATH in dev/prod.env.js
/**
* Source Maps
diff --git a/config/prod.env.js b/config/prod.env.js
index bfcd6d27..e8a2016f 100644
--- a/config/prod.env.js
+++ b/config/prod.env.js
@@ -1,5 +1,6 @@
module.exports = {
NODE_ENV: '"production"',
ENV_CONFIG: '"prod"',
- BASE_API: '"https://api-prod"'
+ BASE_API: '"https://api-prod"',
+ ASSETS_PUBLIC_PATH: '/pleroma/admin/'
}
diff --git a/package.json b/package.json
index 532a58ea..36d058b6 100644
--- a/package.json
+++ b/package.json
@@ -50,7 +50,6 @@
"jszip": "3.1.5",
"lodash": "^4.17.11",
"lodash.debounce": "^4.0.8",
- "mockjs": "1.0.1-beta3",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"screenfull": "4.0.0",
diff --git a/src/api/users.js b/src/api/users.js
index 4b26c162..cdf6476c 100644
--- a/src/api/users.js
+++ b/src/api/users.js
@@ -32,7 +32,7 @@ export async function searchUsers(query, filters, authHost, token, page = 1) {
export async function addRight(nickname, right, authHost, token) {
return await request({
baseURL: baseName(authHost),
- url: `/api/pleroma/admin/permission_group/${nickname}/${right}`,
+ url: `/api/pleroma/admin/users/${nickname}/permission_group/${right}`,
method: 'post',
headers: authHeaders(token)
})
@@ -41,7 +41,7 @@ export async function addRight(nickname, right, authHost, token) {
export async function deleteRight(nickname, right, authHost, token) {
return await request({
baseURL: baseName(authHost),
- url: `/api/pleroma/admin/permission_group/${nickname}/${right}`,
+ url: `/api/pleroma/admin/users/${nickname}/permission_group/${right}`,
method: 'delete',
headers: authHeaders(token)
})
@@ -50,29 +50,29 @@ export async function deleteRight(nickname, right, authHost, token) {
export async function deleteUser(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
- url: `/api/pleroma/admin/user.json?nickname=${nickname}`,
+ url: `/api/pleroma/admin/users?nickname=${nickname}`,
method: 'delete',
headers: authHeaders(token)
})
}
-export async function tagUser(nickname, tag, authHost, token) {
+export async function tagUser(nicknames, tags, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/tag',
method: 'put',
headers: authHeaders(token),
- data: { nicknames: [nickname], tags: [tag] }
+ data: { nicknames, tags }
})
}
-export async function untagUser(nickname, tag, authHost, token) {
+export async function untagUser(nicknames, tags, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/tag',
method: 'delete',
headers: authHeaders(token),
- data: { nicknames: [nickname], tags: [tag] }
+ data: { nicknames, tags }
})
}
diff --git a/src/main.js b/src/main.js
index 7739639d..fc403bbf 100644
--- a/src/main.js
+++ b/src/main.js
@@ -17,7 +17,6 @@ import i18n from './lang' // Internationalization
import './icons' // icon
import './errorLog' // error log
import './permission' // permission control
-import './mock' // simulation data
import * as filters from './filters' // global filters
diff --git a/src/mock/article.js b/src/mock/article.js
deleted file mode 100644
index 45923ddd..00000000
--- a/src/mock/article.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import Mock from 'mockjs'
-import { param2Obj } from '@/utils'
-
-const List = []
-const count = 100
-
-const baseContent = '
我是测试数据我是测试数据
![](https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943)
'
-const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
-
-for (let i = 0; i < count; i++) {
- List.push(Mock.mock({
- id: '@increment',
- timestamp: +Mock.Random.date('T'),
- author: '@first',
- reviewer: '@first',
- title: '@title(5, 10)',
- content_short: '我是测试数据',
- content: baseContent,
- forecast: '@float(0, 100, 2, 2)',
- importance: '@integer(1, 3)',
- 'type|1': ['CN', 'US', 'JP', 'EU'],
- 'status|1': ['published', 'draft', 'deleted'],
- display_time: '@datetime',
- comment_disabled: true,
- pageviews: '@integer(300, 5000)',
- image_uri,
- platforms: ['a-platform']
- }))
-}
-
-export default {
- getList: config => {
- const { importance, type, title, page = 1, limit = 20, sort } = param2Obj(config.url)
-
- let mockList = List.filter(item => {
- if (importance && item.importance !== +importance) return false
- if (type && item.type !== type) return false
- if (title && item.title.indexOf(title) < 0) return false
- return true
- })
-
- if (sort === '-id') {
- mockList = mockList.reverse()
- }
-
- const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
-
- return {
- total: mockList.length,
- items: pageList
- }
- },
- getPv: () => ({
- pvData: [{ key: 'PC', pv: 1024 }, { key: 'mobile', pv: 1024 }, { key: 'ios', pv: 1024 }, { key: 'android', pv: 1024 }]
- }),
- getArticle: (config) => {
- const { id } = param2Obj(config.url)
- for (const article of List) {
- if (article.id === +id) {
- return article
- }
- }
- },
- createArticle: () => ({
- data: 'success'
- }),
- updateArticle: () => ({
- data: 'success'
- })
-}
diff --git a/src/mock/index.js b/src/mock/index.js
deleted file mode 100644
index 3e00e918..00000000
--- a/src/mock/index.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import Mock from 'mockjs'
-import loginAPI from './login'
-import articleAPI from './article'
-import remoteSearchAPI from './remoteSearch'
-import transactionAPI from './transaction'
-
-// 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题
-// https://github.com/nuysoft/Mock/issues/300
-Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
-Mock.XHR.prototype.send = function() {
- if (this.custom.xhr) {
- this.custom.xhr.withCredentials = this.withCredentials || false
- }
- this.proxy_send(...arguments)
-}
-
-// Mock.setup({
-// timeout: '350-600'
-// })
-
-// 登录相关
-Mock.mock(/\/login\/login/, 'post', loginAPI.loginByUsername)
-Mock.mock(/\/login\/logout/, 'post', loginAPI.logout)
-Mock.mock(/\/user\/info\.*/, 'get', loginAPI.getUserInfo)
-
-// 文章相关
-Mock.mock(/\/article\/list/, 'get', articleAPI.getList)
-Mock.mock(/\/article\/detail/, 'get', articleAPI.getArticle)
-Mock.mock(/\/article\/pv/, 'get', articleAPI.getPv)
-Mock.mock(/\/article\/create/, 'post', articleAPI.createArticle)
-Mock.mock(/\/article\/update/, 'post', articleAPI.updateArticle)
-
-// 搜索相关
-Mock.mock(/\/search\/user/, 'get', remoteSearchAPI.searchUser)
-
-// 账单相关
-Mock.mock(/\/transaction\/list/, 'get', transactionAPI.getList)
-
-export default Mock
diff --git a/src/mock/login.js b/src/mock/login.js
deleted file mode 100644
index b9694f09..00000000
--- a/src/mock/login.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { param2Obj } from '@/utils'
-
-const userMap = {
- admin: {
- roles: ['admin'],
- token: 'admin',
- introduction: '我是超级管理员',
- avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
- name: 'Super Admin'
- },
- editor: {
- roles: ['editor'],
- token: 'editor',
- introduction: '我是编辑',
- avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
- name: 'Normal Editor'
- }
-}
-
-export default {
- loginByUsername: config => {
- const { username } = JSON.parse(config.body)
- return userMap[username]
- },
- getUserInfo: config => {
- const { token } = param2Obj(config.url)
- if (userMap[token]) {
- return userMap[token]
- } else {
- return false
- }
- },
- logout: () => 'success'
-}
diff --git a/src/mock/remoteSearch.js b/src/mock/remoteSearch.js
deleted file mode 100644
index b70f6f7d..00000000
--- a/src/mock/remoteSearch.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import Mock from 'mockjs'
-import { param2Obj } from '@/utils'
-
-const NameList = []
-const count = 100
-
-for (let i = 0; i < count; i++) {
- NameList.push(Mock.mock({
- name: '@first'
- }))
-}
-NameList.push({ name: 'mockPan' })
-
-export default {
- searchUser: config => {
- const { name } = param2Obj(config.url)
- const mockNameList = NameList.filter(item => {
- const lowerCaseName = item.name.toLowerCase()
- if (name && lowerCaseName.indexOf(name.toLowerCase()) < 0) return false
- return true
- })
- return { items: mockNameList }
- }
-}
diff --git a/src/mock/transaction.js b/src/mock/transaction.js
deleted file mode 100644
index a17517e4..00000000
--- a/src/mock/transaction.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import Mock from 'mockjs'
-
-const List = []
-const count = 20
-
-for (let i = 0; i < count; i++) {
- List.push(Mock.mock({
- order_no: '@guid()',
- timestamp: +Mock.Random.date('T'),
- username: '@name()',
- price: '@float(1000, 15000, 0, 2)',
- 'status|1': ['success', 'pending']
- }))
-}
-
-export default {
- getList: () => {
- return {
- total: List.length,
- items: List
- }
- }
-}
diff --git a/src/store/modules/users.js b/src/store/modules/users.js
index b5f7a737..1321aa65 100644
--- a/src/store/modules/users.js
+++ b/src/store/modules/users.js
@@ -30,6 +30,15 @@ const users = {
a.nickname.localeCompare(b.nickname)
)
},
+ SWAP_USERS: (state, users) => {
+ const usersWithoutSwapped = users.reduce((acc, user) => {
+ return acc.filter(u => u.id !== user.id)
+ }, state.fetchedUsers)
+
+ state.fetchedUsers = [...usersWithoutSwapped, ...users].sort((a, b) =>
+ a.nickname.localeCompare(b.nickname)
+ )
+ },
SET_COUNT: (state, count) => {
state.totalUsersCount = count
},
@@ -47,6 +56,21 @@ const users = {
}
},
actions: {
+ async AddTag({ commit, getters }, { users, tag }) {
+ const nicknames = users.map(user => user.nickname)
+ await tagUser(nicknames, [tag], getters.authHost, getters.token)
+
+ commit('SWAP_USERS', users.map(user => ({ ...user, tags: [...user.tags, tag] })))
+ },
+ async ClearFilters({ commit, dispatch, state }) {
+ commit('CLEAR_USERS_FILTERS')
+ dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
+ },
+ async DeleteUser({ commit, getters }, user) {
+ await deleteUser(user.nickname, getters.authHost, getters.token)
+ const updatedUser = { ...user, deactivated: true }
+ commit('SWAP_USER', updatedUser)
+ },
async FetchUsers({ commit, state, getters }, { page }) {
const filters = Object.keys(state.filters).filter(filter => state.filters[filter]).join()
const response = await fetchUsers(filters, getters.authHost, getters.token, page)
@@ -58,10 +82,11 @@ const users = {
loadUsers(commit, page, response.data)
},
- async ToggleUserActivation({ commit, getters }, nickname) {
- const response = await toggleUserActivation(nickname, getters.authHost, getters.token)
+ async RemoveTag({ commit, getters }, { users, tag }) {
+ const nicknames = users.map(user => user.nickname)
+ await untagUser(nicknames, [tag], getters.authHost, getters.token)
- commit('SWAP_USER', response.data)
+ commit('SWAP_USERS', users.map(user => ({ ...user, tags: user.tags.filter(userTag => userTag !== tag) })))
},
async SearchUsers({ commit, dispatch, state, getters }, { query, page }) {
if (query.length === 0) {
@@ -77,6 +102,10 @@ const users = {
loadUsers(commit, page, response.data)
}
},
+ async ToggleUserActivation({ commit, getters }, nickname) {
+ const { data } = await toggleUserActivation(nickname, getters.authHost, getters.token)
+ commit('SWAP_USER', data)
+ },
async ToggleUsersFilter({ commit, dispatch, state }, filters) {
const defaultFilters = {
local: false,
@@ -88,10 +117,6 @@ const users = {
commit('SET_USERS_FILTERS', currentFilters)
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
},
- async ClearFilters({ commit, dispatch, state }) {
- commit('CLEAR_USERS_FILTERS')
- dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
- },
async ToggleRight({ commit, getters }, { user, right }) {
user.roles[right]
? await deleteRight(user.nickname, right, getters.authHost, getters.token)
@@ -99,22 +124,6 @@ const users = {
const updatedUser = { ...user, roles: { ...user.roles, [right]: !user.roles[right] }}
commit('SWAP_USER', updatedUser)
- },
- async DeleteUser({ commit, getters }, user) {
- await deleteUser(user.nickname, getters.authHost, getters.token)
- const updatedUser = { ...user, deactivated: true }
- commit('SWAP_USER', updatedUser)
- },
- async ToggleTag({ commit, getters }, { user, tag }) {
- if (user.tags.includes(tag)) {
- await untagUser(user.nickname, tag, getters.authHost, getters.token)
- const updatedUser = { ...user, tags: user.tags.filter(userTag => userTag !== tag) }
- commit('SWAP_USER', updatedUser)
- } else {
- await tagUser(user.nickname, tag, getters.authHost, getters.token)
- const updatedUser = { ...user, tags: [...user.tags, tag] }
- commit('SWAP_USER', updatedUser)
- }
}
}
}
diff --git a/src/views/users/index.vue b/src/views/users/index.vue
index d41f7898..4a186ae3 100644
--- a/src/views/users/index.vue
+++ b/src/views/users/index.vue
@@ -164,9 +164,18 @@ export default {
this.$store.dispatch('FetchUsers', { page: 1 })
},
methods: {
+ activationIcon(status) {
+ return status ? 'el-icon-error' : 'el-icon-success'
+ },
+ getFirstLetter(str) {
+ return str.charAt(0).toUpperCase()
+ },
handleDeactivation({ nickname }) {
this.$store.dispatch('ToggleUserActivation', nickname)
},
+ handleDeletion(user) {
+ this.$store.dispatch('DeleteUser', user)
+ },
handlePageChange(page) {
const searchQuery = this.$store.state.users.searchQuery
if (searchQuery === '') {
@@ -175,26 +184,19 @@ export default {
this.$store.dispatch('SearchUsers', { query: searchQuery, page })
}
},
- showDeactivatedButton(id) {
- return this.$store.state.user.id !== id
- },
showAdminAction({ local, id }) {
return local && this.showDeactivatedButton(id)
},
- activationIcon(status) {
- return status ? 'el-icon-error' : 'el-icon-success'
+ showDeactivatedButton(id) {
+ return this.$store.state.user.id !== id
+ },
+ toggleTag(user, tag) {
+ user.tags.includes(tag)
+ ? this.$store.dispatch('RemoveTag', { users: [user], tag })
+ : this.$store.dispatch('AddTag', { users: [user], tag })
},
toggleUserRight(user, right) {
this.$store.dispatch('ToggleRight', { user, right })
- },
- handleDeletion(user) {
- this.$store.dispatch('DeleteUser', user)
- },
- toggleTag(user, tag) {
- this.$store.dispatch('ToggleTag', { user, tag })
- },
- getFirstLetter(str) {
- return str.charAt(0).toUpperCase()
}
}
}
diff --git a/yarn.lock b/yarn.lock
index 1f7a8a5b..e6bf827d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2486,16 +2486,16 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
-commander@*, commander@^2.13.0, commander@^2.14.1, commander@^2.9.0:
- version "2.19.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
- integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
-
commander@2.17.x, commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
+commander@^2.13.0, commander@^2.14.1, commander@^2.9.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+ integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
commander@~2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
@@ -6645,13 +6645,6 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@
dependencies:
minimist "0.0.8"
-mockjs@1.0.1-beta3:
- version "1.0.1-beta3"
- resolved "https://registry.yarnpkg.com/mockjs/-/mockjs-1.0.1-beta3.tgz#d234f3c27256397564f2c955142e891909537209"
- integrity sha1-0jTzwnJWOXVk8slVFC6JGQlTcgk=
- dependencies:
- commander "*"
-
move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"