Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
pleroma-fe
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
absturztaube
pleroma-fe
Commits
2e35289c
Commit
2e35289c
authored
May 03, 2020
by
HJ
🐼
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial work on settings modal
parent
9b349b40
Changes
26
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
1530 additions
and
927 deletions
+1530
-927
src/App.js
src/App.js
+5
-0
src/App.scss
src/App.scss
+3
-0
src/App.vue
src/App.vue
+4
-3
src/components/mobile_post_status_button/mobile_post_status_button.js
...ts/mobile_post_status_button/mobile_post_status_button.js
+1
-1
src/components/post_status_modal/post_status_modal.js
src/components/post_status_modal/post_status_modal.js
+0
-3
src/components/post_status_modal/post_status_modal.vue
src/components/post_status_modal/post_status_modal.vue
+0
-1
src/components/settings_modal/settings_modal.js
src/components/settings_modal/settings_modal.js
+39
-0
src/components/settings_modal/settings_modal.scss
src/components/settings_modal/settings_modal.scss
+59
-0
src/components/settings_modal/settings_modal.vue
src/components/settings_modal/settings_modal.vue
+31
-0
src/components/settings_modal/tabs/data_import_export.js
src/components/settings_modal/tabs/data_import_export.js
+65
-0
src/components/settings_modal/tabs/data_import_export.vue
src/components/settings_modal/tabs/data_import_export.vue
+43
-0
src/components/settings_modal/tabs/mutes_and_blocks.js
src/components/settings_modal/tabs/mutes_and_blocks.js
+124
-0
src/components/settings_modal/tabs/mutes_and_blocks.vue
src/components/settings_modal/tabs/mutes_and_blocks.vue
+173
-0
src/components/settings_modal/tabs/notifications.js
src/components/settings_modal/tabs/notifications.js
+27
-0
src/components/settings_modal/tabs/notifications.vue
src/components/settings_modal/tabs/notifications.vue
+42
-0
src/components/settings_modal/tabs/profile.js
src/components/settings_modal/tabs/profile.js
+179
-0
src/components/settings_modal/tabs/profile.scss
src/components/settings_modal/tabs/profile.scss
+82
-0
src/components/settings_modal/tabs/profile.vue
src/components/settings_modal/tabs/profile.vue
+213
-0
src/components/settings_modal/tabs/security.js
src/components/settings_modal/tabs/security.js
+106
-0
src/components/settings_modal/tabs/security.vue
src/components/settings_modal/tabs/security.vue
+143
-0
src/components/tab_switcher/tab_switcher.js
src/components/tab_switcher/tab_switcher.js
+6
-1
src/components/tab_switcher/tab_switcher.scss
src/components/tab_switcher/tab_switcher.scss
+154
-66
src/components/user_settings/user_settings.js
src/components/user_settings/user_settings.js
+2
-255
src/components/user_settings/user_settings.vue
src/components/user_settings/user_settings.vue
+0
-597
src/i18n/en.json
src/i18n/en.json
+1
-0
src/modules/interface.js
src/modules/interface.js
+28
-0
No files found.
src/App.js
View file @
2e35289c
...
...
@@ -6,6 +6,7 @@ import InstanceSpecificPanel from './components/instance_specific_panel/instance
import
FeaturesPanel
from
'
./components/features_panel/features_panel.vue
'
import
WhoToFollowPanel
from
'
./components/who_to_follow_panel/who_to_follow_panel.vue
'
import
ChatPanel
from
'
./components/chat_panel/chat_panel.vue
'
import
SettingsModal
from
'
./components/settings_modal/settings_modal.vue
'
import
MediaModal
from
'
./components/media_modal/media_modal.vue
'
import
SideDrawer
from
'
./components/side_drawer/side_drawer.vue
'
import
MobilePostStatusButton
from
'
./components/mobile_post_status_button/mobile_post_status_button.vue
'
...
...
@@ -29,6 +30,7 @@ export default {
SideDrawer
,
MobilePostStatusButton
,
MobileNav
,
SettingsModal
,
UserReportingModal
,
PostStatusModal
},
...
...
@@ -112,6 +114,9 @@ export default {
onSearchBarToggled
(
hidden
)
{
this
.
searchBarHidden
=
hidden
},
openSettingsModal
()
{
this
.
$store
.
dispatch
(
'
openSettingsModal
'
)
},
updateMobileState
()
{
const
mobileLayout
=
windowWidth
()
<=
800
const
changed
=
mobileLayout
!==
this
.
isMobileLayout
...
...
src/App.scss
View file @
2e35289c
...
...
@@ -860,6 +860,7 @@ nav {
}
}
// DELETE
.setting-item
{
border-bottom
:
2px
solid
var
(
--
fg
,
$fallback--fg
);
margin
:
1em
1em
1
.4em
;
...
...
@@ -905,6 +906,8 @@ nav {
max-width
:
6em
;
}
}
// DELETE
.select-multiple
{
display
:
flex
;
.option-list
{
...
...
src/App.vue
View file @
2e35289c
...
...
@@ -46,15 +46,15 @@
@
toggled=
"onSearchBarToggled"
@
click.stop.native
/>
<
router-link
<
a
class=
"mobile-hidden"
:to=
"
{ name: 'settings'}
"
@
click.stop=
"openSettingsModal
"
>
<i
class=
"button-icon icon-cog nav-icon"
:title=
"$t('nav.preferences')"
/>
</
router-link
>
</
a
>
<a
v-if=
"currentUser && currentUser.role === 'admin'"
href=
"/pleroma/admin/#/login-pleroma"
...
...
@@ -122,6 +122,7 @@
<MobilePostStatusButton
/>
<UserReportingModal
/>
<PostStatusModal
/>
<SettingsModal
/>
<portal-target
name=
"modal"
/>
</div>
</
template
>
...
...
src/components/mobile_post_status_button/mobile_post_status_button.js
View file @
2e35289c
...
...
@@ -52,7 +52,7 @@ const MobilePostStatusButton = {
window
.
removeEventListener
(
'
scroll
'
,
this
.
handleScrollEnd
)
},
openPostForm
()
{
this
.
$store
.
dispatch
(
'
open
PostStatu
sModal
'
)
this
.
$store
.
dispatch
(
'
open
Setting
sModal
'
)
},
handleOSK
()
{
// This is a big hack: we're guessing from changed window sizes if the
...
...
src/components/post_status_modal/post_status_modal.js
View file @
2e35289c
...
...
@@ -13,9 +13,6 @@ const PostStatusModal = {
}
},
computed
:
{
isLoggedIn
()
{
return
!!
this
.
$store
.
state
.
users
.
currentUser
},
modalActivated
()
{
return
this
.
$store
.
state
.
postStatus
.
modalActivated
},
...
...
src/components/post_status_modal/post_status_modal.vue
View file @
2e35289c
<
template
>
<Modal
v-if=
"isLoggedIn && !resettingForm"
:is-open=
"modalActivated"
class=
"post-form-modal-view"
@
backdropClicked=
"closeModal"
...
...
src/components/settings_modal/settings_modal.js
0 → 100644
View file @
2e35289c
import
Modal
from
'
../modal/modal.vue
'
import
TabSwitcher
from
'
../tab_switcher/tab_switcher.js
'
import
Profile
from
'
./tabs/profile.vue
'
import
Security
from
'
./tabs/security.vue
'
import
Notifications
from
'
./tabs/notifications.vue
'
import
DataImportExport
from
'
./tabs/data_import_export.vue
'
import
MutesAndBlocks
from
'
./tabs/mutes_and_blocks.vue
'
const
SettingsModal
=
{
components
:
{
Modal
,
TabSwitcher
,
Profile
,
Security
,
Notifications
,
DataImportExport
,
MutesAndBlocks
},
data
()
{
return
{
resettingForm
:
false
}
},
computed
:
{
isLoggedIn
()
{
return
!!
this
.
$store
.
state
.
users
.
currentUser
},
modalActivated
()
{
return
this
.
$store
.
state
.
interface
.
settingsModalState
!==
'
hidden
'
}
},
watch
:
{
},
methods
:
{
}
}
export
default
SettingsModal
src/components/settings_modal/settings_modal.scss
0 → 100644
View file @
2e35289c
@import
'../../_variables.scss'
;
.settings-modal
{
.settings_tab-switcher
{
height
:
100%
;
}
.settings-modal-panel
{
width
:
1000px
;
max-width
:
90vw
;
height
:
90vh
;
}
.panel-body
{
overflow-y
:
hidden
;
}
.setting-item
{
border-bottom
:
2px
solid
var
(
--
fg
,
$fallback--fg
);
margin
:
1em
1em
1
.4em
;
padding-bottom
:
1
.4em
;
>
div
{
margin-bottom
:
.5em
;
&
:last-child
{
margin-bottom
:
0
;
}
}
&
:last-child
{
border-bottom
:
none
;
padding-bottom
:
0
;
margin-bottom
:
1em
;
}
select
{
min-width
:
10em
;
}
textarea
{
width
:
100%
;
max-width
:
100%
;
height
:
100px
;
}
.unavailable
,
.unavailable
i
{
color
:
var
(
--
cRed
,
$fallback--cRed
);
color
:
$fallback--cRed
;
}
.btn
{
min-height
:
28px
;
min-width
:
10em
;
padding
:
0
2em
;
}
.number-input
{
max-width
:
6em
;
}
}
}
src/components/settings_modal/settings_modal.vue
0 → 100644
View file @
2e35289c
<
template
>
<Modal
v-if=
"isLoggedIn && !resettingForm"
:is-open=
"modalActivated"
class=
"settings-modal"
>
<div
class=
"settings-modal-panel panel"
>
<div
class=
"panel-heading"
>
{{
$t
(
'
settings.settings
'
)
}}
</div>
<div
class=
"panel-body"
>
<tab-switcher
class=
"settings_tab-switcher"
:sideTabBar=
"true"
:scrollableTabs=
"true"
ref=
"tabSwitcher"
>
<div
:label=
"$t('settings.profile_tab')"
><Profile
/></div>
<div
:label=
"$t('settings.security_tab')"
><Security
/></div>
<div
:label=
"$t('settings.notifications')"
><Notifications
/></div>
<div
:label=
"$t('settings.data_import_export_tab')"
><DataImportExport
/></div>
<div
:label=
"$t('settings.mutes_and_blocks')"
><MutesAndBlocks
/></div>
</tab-switcher>
</div>
</div>
</Modal>
</
template
>
<
script
src=
"./settings_modal.js"
></
script
>
<
style
src=
"./settings_modal.scss"
lang=
"scss"
></
style
>
src/components/settings_modal/tabs/data_import_export.js
0 → 100644
View file @
2e35289c
import
Importer
from
'
../../importer/importer.vue
'
import
Exporter
from
'
../../exporter/exporter.vue
'
import
Checkbox
from
'
../../checkbox/checkbox.vue
'
const
DataImportExport
=
{
data
()
{
return
{
activeTab
:
'
profile
'
,
newDomainToMute
:
''
}
},
created
()
{
this
.
$store
.
dispatch
(
'
fetchTokens
'
)
},
components
:
{
Importer
,
Exporter
,
Checkbox
},
computed
:
{
user
()
{
return
this
.
$store
.
state
.
users
.
currentUser
}
},
methods
:
{
getFollowsContent
()
{
return
this
.
$store
.
state
.
api
.
backendInteractor
.
exportFriends
({
id
:
this
.
$store
.
state
.
users
.
currentUser
.
id
})
.
then
(
this
.
generateExportableUsersContent
)
},
getBlocksContent
()
{
return
this
.
$store
.
state
.
api
.
backendInteractor
.
fetchBlocks
()
.
then
(
this
.
generateExportableUsersContent
)
},
importFollows
(
file
)
{
return
this
.
$store
.
state
.
api
.
backendInteractor
.
importFollows
({
file
})
.
then
((
status
)
=>
{
if
(
!
status
)
{
throw
new
Error
(
'
failed
'
)
}
})
},
importBlocks
(
file
)
{
return
this
.
$store
.
state
.
api
.
backendInteractor
.
importBlocks
({
file
})
.
then
((
status
)
=>
{
if
(
!
status
)
{
throw
new
Error
(
'
failed
'
)
}
})
},
generateExportableUsersContent
(
users
)
{
// Get addresses
return
users
.
map
((
user
)
=>
{
// check is it's a local user
if
(
user
&&
user
.
is_local
)
{
// append the instance address
// eslint-disable-next-line no-undef
return
user
.
screen_name
+
'
@
'
+
location
.
hostname
}
return
user
.
screen_name
}).
join
(
'
\n
'
)
}
}
}
export
default
DataImportExport
src/components/settings_modal/tabs/data_import_export.vue
0 → 100644
View file @
2e35289c
<
template
>
<div
:label=
"$t('settings.data_import_export_tab')"
>
<div
class=
"setting-item"
>
<h2>
{{
$t
(
'
settings.follow_import
'
)
}}
</h2>
<p>
{{
$t
(
'
settings.import_followers_from_a_csv_file
'
)
}}
</p>
<Importer
:submit-handler=
"importFollows"
:success-message=
"$t('settings.follows_imported')"
:error-message=
"$t('settings.follow_import_error')"
/>
</div>
<div
class=
"setting-item"
>
<h2>
{{
$t
(
'
settings.follow_export
'
)
}}
</h2>
<Exporter
:get-content=
"getFollowsContent"
filename=
"friends.csv"
:export-button-label=
"$t('settings.follow_export_button')"
/>
</div>
<div
class=
"setting-item"
>
<h2>
{{
$t
(
'
settings.block_import
'
)
}}
</h2>
<p>
{{
$t
(
'
settings.import_blocks_from_a_csv_file
'
)
}}
</p>
<Importer
:submit-handler=
"importBlocks"
:success-message=
"$t('settings.blocks_imported')"
:error-message=
"$t('settings.block_import_error')"
/>
</div>
<div
class=
"setting-item"
>
<h2>
{{
$t
(
'
settings.block_export
'
)
}}
</h2>
<Exporter
:get-content=
"getBlocksContent"
filename=
"blocks.csv"
:export-button-label=
"$t('settings.block_export_button')"
/>
</div>
</div>
</
template
>
<
script
src=
"./data_import_export.js"
></
script
>
<!-- <style lang="scss" src="./profile.scss"></style> -->
src/components/settings_modal/tabs/mutes_and_blocks.js
0 → 100644
View file @
2e35289c
import
get
from
'
lodash/get
'
import
map
from
'
lodash/map
'
import
reject
from
'
lodash/reject
'
import
Autosuggest
from
'
../../autosuggest/autosuggest.vue
'
import
TabSwitcher
from
'
../../tab_switcher/tab_switcher.js
'
import
BlockCard
from
'
../../block_card/block_card.vue
'
import
MuteCard
from
'
../../mute_card/mute_card.vue
'
import
DomainMuteCard
from
'
../../domain_mute_card/domain_mute_card.vue
'
import
SelectableList
from
'
../../selectable_list/selectable_list.vue
'
import
ProgressButton
from
'
../../progress_button/progress_button.vue
'
import
withSubscription
from
'
../../../hocs/with_subscription/with_subscription
'
import
Checkbox
from
'
../../checkbox/checkbox.vue
'
const
BlockList
=
withSubscription
({
fetch
:
(
props
,
$store
)
=>
$store
.
dispatch
(
'
fetchBlocks
'
),
select
:
(
props
,
$store
)
=>
get
(
$store
.
state
.
users
.
currentUser
,
'
blockIds
'
,
[]),
childPropName
:
'
items
'
})(
SelectableList
)
const
MuteList
=
withSubscription
({
fetch
:
(
props
,
$store
)
=>
$store
.
dispatch
(
'
fetchMutes
'
),
select
:
(
props
,
$store
)
=>
get
(
$store
.
state
.
users
.
currentUser
,
'
muteIds
'
,
[]),
childPropName
:
'
items
'
})(
SelectableList
)
const
DomainMuteList
=
withSubscription
({
fetch
:
(
props
,
$store
)
=>
$store
.
dispatch
(
'
fetchDomainMutes
'
),
select
:
(
props
,
$store
)
=>
get
(
$store
.
state
.
users
.
currentUser
,
'
domainMutes
'
,
[]),
childPropName
:
'
items
'
})(
SelectableList
)
const
MutesAndBlocks
=
{
data
()
{
return
{
activeTab
:
'
profile
'
,
newDomainToMute
:
''
}
},
created
()
{
this
.
$store
.
dispatch
(
'
fetchTokens
'
)
},
components
:
{
TabSwitcher
,
BlockList
,
MuteList
,
DomainMuteList
,
BlockCard
,
MuteCard
,
DomainMuteCard
,
ProgressButton
,
Autosuggest
,
Checkbox
},
methods
:
{
importFollows
(
file
)
{
return
this
.
$store
.
state
.
api
.
backendInteractor
.
importFollows
({
file
})
.
then
((
status
)
=>
{
if
(
!
status
)
{
throw
new
Error
(
'
failed
'
)
}
})
},
importBlocks
(
file
)
{
return
this
.
$store
.
state
.
api
.
backendInteractor
.
importBlocks
({
file
})
.
then
((
status
)
=>
{
if
(
!
status
)
{
throw
new
Error
(
'
failed
'
)
}
})
},
generateExportableUsersContent
(
users
)
{
// Get addresses
return
users
.
map
((
user
)
=>
{
// check is it's a local user
if
(
user
&&
user
.
is_local
)
{
// append the instance address
// eslint-disable-next-line no-undef
return
user
.
screen_name
+
'
@
'
+
location
.
hostname
}
return
user
.
screen_name
}).
join
(
'
\n
'
)
},
activateTab
(
tabName
)
{
this
.
activeTab
=
tabName
},
filterUnblockedUsers
(
userIds
)
{
return
reject
(
userIds
,
(
userId
)
=>
{
const
user
=
this
.
$store
.
getters
.
findUser
(
userId
)
return
!
user
||
user
.
statusnet_blocking
||
user
.
id
===
this
.
$store
.
state
.
users
.
currentUser
.
id
})
},
filterUnMutedUsers
(
userIds
)
{
return
reject
(
userIds
,
(
userId
)
=>
{
const
user
=
this
.
$store
.
getters
.
findUser
(
userId
)
return
!
user
||
user
.
muted
||
user
.
id
===
this
.
$store
.
state
.
users
.
currentUser
.
id
})
},
queryUserIds
(
query
)
{
return
this
.
$store
.
dispatch
(
'
searchUsers
'
,
query
)
.
then
((
users
)
=>
map
(
users
,
'
id
'
))
},
blockUsers
(
ids
)
{
return
this
.
$store
.
dispatch
(
'
blockUsers
'
,
ids
)
},
unblockUsers
(
ids
)
{
return
this
.
$store
.
dispatch
(
'
unblockUsers
'
,
ids
)
},
muteUsers
(
ids
)
{
return
this
.
$store
.
dispatch
(
'
muteUsers
'
,
ids
)
},
unmuteUsers
(
ids
)
{
return
this
.
$store
.
dispatch
(
'
unmuteUsers
'
,
ids
)
},
unmuteDomains
(
domains
)
{
return
this
.
$store
.
dispatch
(
'
unmuteDomains
'
,
domains
)
},
muteDomain
()
{
return
this
.
$store
.
dispatch
(
'
muteDomain
'
,
this
.
newDomainToMute
)
.
then
(()
=>
{
this
.
newDomainToMute
=
''
})
}
}
}
export
default
MutesAndBlocks
src/components/settings_modal/tabs/mutes_and_blocks.vue
0 → 100644
View file @
2e35289c
<
template
>
<tab-switcher>
<div
:label=
"$t('settings.blocks_tab')"
>
<div
class=
"profile-edit-usersearch-wrapper"
>
<Autosuggest
:filter=
"filterUnblockedUsers"
:query=
"queryUserIds"
:placeholder=
"$t('settings.search_user_to_block')"
>
<BlockCard
slot-scope=
"row"
:user-id=
"row.item"
/>
</Autosuggest>
</div>
<BlockList
:refresh=
"true"
:get-key=
"identity"
>
<template
slot=
"header"
slot-scope=
"
{selected}"
>
<div
class=
"profile-edit-bulk-actions"
>
<ProgressButton
v-if=
"selected.length > 0"
class=
"btn btn-default"
:click=
"() => blockUsers(selected)"
>
{{
$t
(
'
user_card.block
'
)
}}
<template
slot=
"progress"
>
{{
$t
(
'
user_card.block_progress
'
)
}}
</
template
>
</ProgressButton>
<ProgressButton
v-if=
"selected.length > 0"
class=
"btn btn-default"
:click=
"() => unblockUsers(selected)"
>
{{ $t('user_card.unblock') }}
<
template
slot=
"progress"
>
{{
$t
(
'
user_card.unblock_progress
'
)
}}
</
template
>
</ProgressButton>
</div>
</template>
<
template
slot=
"item"
slot-scope=
"{item}"
>
<BlockCard
:user-id=
"item"
/>
</
template
>
<
template
slot=
"empty"
>
{{
$t
(
'
settings.no_blocks
'
)
}}
</
template
>
</BlockList>
</div>
<div
:label=
"$t('settings.mutes_tab')"
>
<tab-switcher>
<div
label=
"Users"
>
<div
class=
"profile-edit-usersearch-wrapper"
>
<Autosuggest
:filter=
"filterUnMutedUsers"
:query=
"queryUserIds"
:placeholder=
"$t('settings.search_user_to_mute')"
>
<MuteCard
slot-scope=
"row"
:user-id=
"row.item"
/>
</Autosuggest>
</div>
<MuteList
:refresh=
"true"
:get-key=
"identity"
>
<
template
slot=
"header"
slot-scope=
"{selected}"
>
<div
class=
"profile-edit-bulk-actions"
>
<ProgressButton
v-if=
"selected.length > 0"
class=
"btn btn-default"
:click=
"() => muteUsers(selected)"
>
{{
$t
(
'
user_card.mute
'
)
}}
<template
slot=
"progress"
>
{{
$t
(
'
user_card.mute_progress
'
)
}}
</
template
>
</ProgressButton>
<ProgressButton
v-if=
"selected.length > 0"
class=
"btn btn-default"
:click=
"() => unmuteUsers(selected)"
>
{{ $t('user_card.unmute') }}
<
template
slot=
"progress"
>
{{
$t
(
'
user_card.unmute_progress
'
)
}}
</
template
>
</ProgressButton>
</div>
</template>
<
template
slot=
"item"
slot-scope=
"{item}"
>
<MuteCard
:user-id=
"item"
/>
</
template
>
<
template
slot=
"empty"
>
{{
$t
(
'
settings.no_mutes
'
)
}}
</
template
>
</MuteList>
</div>
<div
:label=
"$t('settings.domain_mutes')"
>
<div
class=
"profile-edit-domain-mute-form"
>
<input
v-model=
"newDomainToMute"
:placeholder=
"$t('settings.type_domains_to_mute')"
type=
"text"
@
keyup.enter=
"muteDomain"
>
<ProgressButton
class=
"btn btn-default"
:click=
"muteDomain"
>
{{ $t('domain_mute_card.mute') }}