diff --git a/CHANGELOG.md b/CHANGELOG.md index babde03d..0f51d123 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +### Changed + +- Statuses count changes when an instance is selected and shows the amount of statuses from an originating instance +- Add a dialog window with a confirmation when a remove button is clicked on the Settings page +- Disable tab on the Settings page if there are no settings on this tab that can be changed in Admin FE +- Settings that can't be altered in Admin FE are removed: HTTP Signatures settings, Federation publisher modules and Oban Repo + +### Fixed + +- Send `true` and `false` as booleans if they are values of single selects on the Settings page + +## [2.0.3] - 2020-04-29 + ### Added - Link settings that enable registrations and invites diff --git a/src/api/__mocks__/peers.js b/src/api/__mocks__/peers.js new file mode 100644 index 00000000..da61938f --- /dev/null +++ b/src/api/__mocks__/peers.js @@ -0,0 +1,4 @@ +export async function fetchPeers(authHost, token) { + const data = ['lain.com', 'heaven.com'] + return Promise.resolve({ data }) +} diff --git a/src/api/__mocks__/status.js b/src/api/__mocks__/status.js index 0e7bc9fb..c8f98545 100644 --- a/src/api/__mocks__/status.js +++ b/src/api/__mocks__/status.js @@ -5,3 +5,66 @@ export async function changeStatusScope(id, sensitive, visibility, authHost, tok export async function deleteStatus(id, authHost, token) { return Promise.resolve() } + +export async function fetchStatusesByInstance({ instance, authHost, token, pageSize, page }) { + let data + if (pageSize === 1) { + data = page === 1 || page === 2 + ? [{ + 'account': { + 'avatar': 'http://localhost:4000/images/avi.png', + 'display_name': 'sky', + 'url': 'http://localhost:4000/users/sky' + }, + 'content': 'A nice young couple contacted us from Brazil to decorate their newly acquired apartment.', + 'created_at': '2020-01-31T18:20:01.000Z', + 'id': '9rZIr0Jzao5Gjgfmro', + 'sensitive': false, + 'url': 'http://localhost:4000/objects/7af9abbd-fb6c-4318-aeb7-6636c138ac98', + 'visibility': 'unlisted' + }] + : [] + } else { + data = [ + { + 'account': { + 'avatar': 'http://localhost:4000/images/avi.png', + 'display_name': 'sky', + 'url': 'http://localhost:4000/users/sky' + }, + 'content': 'A nice young couple contacted us from Brazil to decorate their newly acquired apartment.', + 'created_at': '2020-01-31T18:20:01.000Z', + 'id': '9rZIr0Jzao5Gjgfmro', + 'sensitive': false, + 'url': 'http://localhost:4000/objects/7af9abbd-fb6c-4318-aeb7-6636c138ac98', + 'visibility': 'unlisted' + }, + { + 'account': { + 'avatar': 'http://localhost:4000/images/avi.png', + 'display_name': 'sky', + 'url': 'http://localhost:4000/users/sky' + }, + 'content': 'the happiest man ever', + 'created_at': '2019-11-23T12:56:18.000Z', + 'id': '9pFoVfWMU3A96Rzq3k', + 'sensitive': false, + 'url': 'http://localhost:4000/objects/449c90fe-c457-4c64-baf2-fe6d0a59ca25', + 'visibility': 'unlisted' + }] + } + return Promise.resolve({ data }) +} + +export async function fetchStatusesCount(instance, authHost, token) { + const data = instance === 'heaven.com' + ? { + 'status_visibility': + { 'direct': 1, 'private': 2, 'public': 3, 'unlisted': 0 } + } + : { + 'status_visibility': + { 'direct': 4, 'private': 10, 'public': 4, 'unlisted': 10 } + } + return Promise.resolve({ data }) +} diff --git a/src/api/emojiPacks.js b/src/api/emojiPacks.js index cc07b1b6..61319cec 100644 --- a/src/api/emojiPacks.js +++ b/src/api/emojiPacks.js @@ -2,22 +2,77 @@ import request from '@/utils/request' import { getToken } from '@/utils/auth' import { baseName } from './utils' -import _ from 'lodash' +export async function addNewEmojiFile(packName, file, shortcode, filename, host, token) { + const data = new FormData() + if (filename.trim() !== '') { + data.set('filename', filename) + } + if (shortcode.trim() !== '') { + data.set('shortcode', shortcode) + } + data.set('file', file) -export async function deletePack(host, token, name) { return await request({ baseURL: baseName(host), - url: `/api/pleroma/emoji/packs/${name}`, + url: `/api/pleroma/emoji/packs/${packName}/files`, + method: 'post', + headers: authHeaders(token), + data + }) +} + +export function addressOfEmojiInPack(host, packName, name) { + return `${baseName(host)}/emoji/${packName}/${name}` +} + +export async function createPack(host, token, packName) { + return await request({ + baseURL: baseName(host), + url: `/api/pleroma/emoji/packs/${packName}`, + method: 'post', + headers: authHeaders(token) + }) +} + +export async function deleteEmojiFile(packName, shortcode, host, token) { + return await request({ + baseURL: baseName(host), + url: `/api/pleroma/emoji/packs/${packName}/files`, + method: 'delete', + headers: authHeaders(token), + data: { shortcode } + }) +} + +export async function deletePack(host, token, packName) { + return await request({ + baseURL: baseName(host), + url: `/api/pleroma/emoji/packs/${packName}`, method: 'delete', headers: authHeaders(token) }) } -export async function reloadEmoji(host, token) { +export async function downloadFrom(host, instance, packName, as, token) { + if (as.trim() === '') { + as = null + } + return await request({ baseURL: baseName(host), - url: '/api/pleroma/admin/reload_emoji', + url: '/api/pleroma/emoji/packs/download', method: 'post', + headers: authHeaders(token), + data: { url: baseName(instance), name: packName, as }, + timeout: 0 + }) +} + +export async function fetchPack(packName, host, token) { + return await request({ + baseURL: baseName(host), + url: `/api/pleroma/emoji/packs/${packName}`, + method: 'get', headers: authHeaders(token) }) } @@ -25,17 +80,8 @@ export async function reloadEmoji(host, token) { export async function importFromFS(host, token) { return await request({ baseURL: baseName(host), - url: '/api/pleroma/emoji/packs/import_from_fs', - method: 'post', - headers: authHeaders(token) - }) -} - -export async function createPack(host, token, name) { - return await request({ - baseURL: baseName(host), - url: `/api/pleroma/emoji/packs/${name}`, - method: 'put', + url: '/api/pleroma/emoji/packs/import', + method: 'get', headers: authHeaders(token) }) } @@ -51,106 +97,40 @@ export async function listPacks(host) { export async function listRemotePacks(host, token, instance) { return await request({ baseURL: baseName(host), - url: `/api/pleroma/emoji/packs/list_from`, - method: 'post', - headers: authHeaders(token), - data: { instance_address: baseName(instance) } + url: `/api/pleroma/emoji/packs/remote?url=${baseName(instance)}`, + method: 'get', + headers: authHeaders(token) }) } -export async function downloadFrom(host, instance_address, pack_name, as, token) { - if (as.trim() === '') { - as = null - } - +export async function reloadEmoji(host, token) { return await request({ baseURL: baseName(host), - url: '/api/pleroma/emoji/packs/download_from', + url: '/api/pleroma/admin/reload_emoji', method: 'post', - headers: authHeaders(token), - data: { instance_address: baseName(instance_address), pack_name, as }, - timeout: 0 + headers: authHeaders(token) }) } -export async function savePackMetadata(host, token, name, new_data) { +export async function savePackMetadata(host, token, packName, metadata) { return await request({ baseURL: baseName(host), - url: `/api/pleroma/emoji/packs/${name}/update_metadata`, - method: 'post', + url: `/api/pleroma/emoji/packs/${packName}`, + method: 'patch', headers: authHeaders(token), - data: { name, new_data }, + data: { metadata }, timeout: 0 // This might take a long time }) } -function fileUpdateFormData(d) { - const data = new FormData() - - _.each(d, (v, k) => { - data.set(k, v) - }) - - return data -} - -export async function updatePackFile(host, token, args) { - let data = null - - switch (args.action) { - case 'add': { - const { shortcode, file, fileName } = args - - data = fileUpdateFormData({ - action: 'add', - shortcode: shortcode, - file: file - }) - if (fileName.trim() !== '') { - data.set('filename', fileName) - } - - break - } - - case 'update': { - const { oldName, newName, newFilename } = args - - data = fileUpdateFormData({ - action: 'update', - shortcode: oldName, - new_shortcode: newName, - new_filename: newFilename - }) - - break - } - - case 'remove': { - const { name } = args - data = fileUpdateFormData({ - action: 'remove', - shortcode: name - }) - - break - } - } - - const { packName } = args - +export async function updateEmojiFile(packName, shortcode, newShortcode, newFilename, force, host, token) { return await request({ baseURL: baseName(host), - url: `/api/pleroma/emoji/packs/${packName}/update_file`, - method: 'post', + url: `/api/pleroma/emoji/packs/${packName}/files`, + method: 'patch', headers: authHeaders(token), - data: data, - timeout: 0 + data: { shortcode, new_shortcode: newShortcode, new_filename: newFilename, force } }) } -export function addressOfEmojiInPack(host, packName, name) { - return `${baseName(host)}/emoji/${packName}/${name}` -} - const authHeaders = (token) => token ? { 'Authorization': `Bearer ${getToken()}` } : {} diff --git a/src/api/status.js b/src/api/status.js index 032f26fb..0f3455c7 100644 --- a/src/api/status.js +++ b/src/api/status.js @@ -39,10 +39,10 @@ export async function fetchStatuses({ godmode, localOnly, authHost, token, pageS }) } -export async function fetchStatusesCount(authHost, token) { +export async function fetchStatusesCount(instance, authHost, token) { return await request({ baseURL: baseName(authHost), - url: `/api/pleroma/admin/stats`, + url: instance ? `/api/pleroma/admin/stats?instance=${instance}` : `/api/pleroma/admin/stats`, method: 'get', headers: authHeaders(token) }) diff --git a/src/lang/en.js b/src/lang/en.js index 314672f8..2e504315 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -387,7 +387,8 @@ export default { corsPlug: 'CORS plug config', instanceReboot: 'Reboot Instance', restartApp: 'You must restart the instance to apply settings', - restartSuccess: 'Instance rebooted successfully!' + restartSuccess: 'Instance rebooted successfully!', + removeSettingConfirmation: 'Are you sure you want to remove this setting\'s value from the database?' }, invites: { inviteTokens: 'Invite tokens', diff --git a/src/store/modules/emojiPacks.js b/src/store/modules/emojiPacks.js index f92e0fa5..e4748c26 100644 --- a/src/store/modules/emojiPacks.js +++ b/src/store/modules/emojiPacks.js @@ -1,13 +1,16 @@ import { + addNewEmojiFile, + createPack, + deleteEmojiFile, + deletePack, + downloadFrom, + importFromFS, listPacks, listRemotePacks, - downloadFrom, reloadEmoji, - createPack, - deletePack, savePackMetadata, - importFromFS, - updatePackFile } from '@/api/emojiPacks' + updateEmojiFile +} from '@/api/emojiPacks' import i18n from '@/lang' import { Message } from 'element-ui' @@ -49,6 +52,36 @@ const packs = { } }, actions: { + async AddNewEmojiFile({ commit, getters }, { packName, file, shortcode, filename }) { + let result + try { + result = await addNewEmojiFile(packName, file, shortcode, filename, getters.authHost, getters.token) + } catch (_e) { + return + } + Message({ + message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`, + type: 'success', + duration: 5 * 1000 + }) + + commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data }) + }, + async DeleteEmojiFile({ commit, getters }, { packName, shortcode }) { + let result + try { + result = await deleteEmojiFile(packName, shortcode, getters.authHost, getters.token) + } catch (_e) { + return + } + Message({ + message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`, + type: 'success', + duration: 5 * 1000 + }) + + commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data }) + }, async CreatePack({ getters }, { name }) { await createPack(getters.authHost, getters.token, name) }, @@ -116,20 +149,23 @@ const packs = { commit('SET_REMOTE_INSTANCE', remoteInstance) commit('SET_REMOTE_PACKS', data) }, - async UpdateAndSavePackFile({ commit, getters }, args) { - const result = await updatePackFile(getters.authHost, getters.token, args) - - if (result.status === 200) { - const { packName } = args - - Message({ - message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`, - type: 'success', - duration: 5 * 1000 - }) - - commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data }) + SetRemoteInstance({ commit }, instance) { + commit('SET_REMOTE_INSTANCE', instance) + }, + async UpdateEmojiFile({ commit, getters }, { packName, shortcode, newShortcode, newFilename, force }) { + let result + try { + result = await updateEmojiFile(packName, shortcode, newShortcode, newFilename, force, getters.authHost, getters.token) + } catch (_e) { + return } + Message({ + message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`, + type: 'success', + duration: 5 * 1000 + }) + + commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data }) }, async UpdateLocalPackVal({ commit }, args) { commit('UPDATE_LOCAL_PACK_VAL', args) diff --git a/src/store/modules/normalizers.js b/src/store/modules/normalizers.js index 6eecebca..c146d60e 100644 --- a/src/store/modules/normalizers.js +++ b/src/store/modules/normalizers.js @@ -1,5 +1,14 @@ import _ from 'lodash' +export const getBooleanValue = value => { + if (value === 'true') { + return true + } else if (value === 'false') { + return false + } + return value +} + export const checkPartialUpdate = (settings, updatedSettings, description) => { return Object.keys(updatedSettings).reduce((acc, group) => { acc[group] = Object.keys(updatedSettings[group]).reduce((acc, key) => { diff --git a/src/store/modules/status.js b/src/store/modules/status.js index af29f389..74271afa 100644 --- a/src/store/modules/status.js +++ b/src/store/modules/status.js @@ -68,6 +68,14 @@ const status = { dispatch('FetchStatus', statusId) } }, + ClearState({ commit }) { + commit('CHANGE_SELECTED_INSTANCE', '') + commit('SET_STATUSES_BY_INSTANCE', []) + commit('CHANGE_LOCAL_CHECKBOX_VALUE', false) + commit('CHANGE_GODMODE_CHECKBOX_VALUE', false) + commit('SET_ALL_LOADED', false) + commit('CHANGE_PAGE', 1) + }, async DeleteStatus({ dispatch, getters }, { statusId, reportCurrentPage, userId, godmode, fetchStatusesByInstance }) { await deleteStatus(statusId, getters.authHost, getters.token) if (reportCurrentPage !== 0) { // called from Reports @@ -89,12 +97,13 @@ const status = { }, async FetchStatusesCount({ commit, getters }) { commit('SET_LOADING', true) - const { data } = await fetchStatusesCount(getters.authHost, getters.token) + const { data } = await fetchStatusesCount(instance, getters.authHost, getters.token) commit('SET_STATUS_VISIBILITY', data.status_visibility) commit('SET_LOADING', false) }, - async FetchStatusesByInstance({ commit, getters, state, rootState }) { + async FetchStatusesByInstance({ commit, dispatch, getters, state, rootState }) { commit('SET_LOADING', true) + dispatch('FetchStatusesCount', state.statusesByInstance.selectedInstance) if (state.statusesByInstance.selectedInstance === '') { commit('SET_STATUSES_BY_INSTANCE', []) } else { diff --git a/src/views/emojiPacks/components/LocalEmojiPack.vue b/src/views/emojiPacks/components/LocalEmojiPack.vue index 917ff4dd..c03ba580 100644 --- a/src/views/emojiPacks/components/LocalEmojiPack.vue +++ b/src/views/emojiPacks/components/LocalEmojiPack.vue @@ -44,11 +44,11 @@ @@ -96,9 +96,9 @@ export default { if (this.isMobile) { return '90px' } else if (this.isTablet) { - return '120px' + return '155px' } else { - return '120px' + return '155px' } }, share: { diff --git a/src/views/emojiPacks/components/NewEmojiUploader.vue b/src/views/emojiPacks/components/NewEmojiUploader.vue index f364b49e..5229e566 100644 --- a/src/views/emojiPacks/components/NewEmojiUploader.vue +++ b/src/views/emojiPacks/components/NewEmojiUploader.vue @@ -1,7 +1,7 @@