Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions js/user_migration-personal-settings.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/user_migration-personal-settings.js.map

Large diffs are not rendered by default.

161 changes: 92 additions & 69 deletions src/components/ExportSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,74 +24,84 @@
<div class="section">
<h2>{{ t('user_migration', 'Export') }}</h2>

<h3 class="settings-hint">
{{ t('user_migration', 'Please select the data you want to export') }}
</h3>

<div class="section__grid">
<!-- Base user data is permanently enabled -->
<div class="section__checkbox">
<CheckboxRadioSwitch :checked="true"
:disabled="true">
{{ t('user_migration', 'User information and settings') }}
</CheckboxRadioSwitch>
<em class="section__description">{{ t('user_migration', 'Basic user information including user ID and display name as well as your settings') }}</em>
<template v-if="!loading">
<h3 class="settings-hint">
{{ t('user_migration', 'Please select the data you want to export') }}
</h3>

<div class="section__grid">
<!-- Base user data is permanently enabled -->
<div class="section__checkbox">
<CheckboxRadioSwitch :checked="true"
:disabled="true">
{{ t('user_migration', 'User information and settings') }}
</CheckboxRadioSwitch>
<em class="section__description">{{ t('user_migration', 'Basic user information including user ID and display name as well as your settings') }}</em>
</div>
<div v-for="({id, displayName, description}) in migrators"
:key="id"
class="section__checkbox">
<CheckboxRadioSwitch name="migrators"
:value="id"
:checked.sync="selectedMigrators">
{{ displayName }}
</CheckboxRadioSwitch>
<em class="section__description">{{ description }}</em>
</div>
</div>
<div v-for="({id, displayName, description}) in sortedMigrators"
:key="id"
class="section__checkbox">
<CheckboxRadioSwitch name="migrators"
:value="id"
:checked.sync="selectedMigrators">
{{ displayName }}
</CheckboxRadioSwitch>
<em class="section__description">{{ description }}</em>
</div>
</div>

<div v-if="status.current !== 'export'"
class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Export your data')"
:disabled="status.current === 'import'"
@click.stop.prevent="startExport">
<template #icon>
<PackageDown title="" :size="20" />
</template>
{{ t('user_migration', 'Export') }}
</Button>
<div v-if="startingExport" class="icon-loading" />
</div>
<div v-else class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Show export status')"
:disabled="status.current === 'import'"
@click.stop.prevent="openModal">
{{ t('user_migration', 'Show status') }}
</Button>
<span class="settings-hint">{{ status.status === 'waiting' ? t('user_migration', 'Export queued') : t('user_migration', 'Export in progress…') }}</span>
</div>

<Modal v-if="modalOpened"
@close="closeModal">
<div class="section__modal">
<EmptyContent>
{{ modalMessage }}

<div v-if="status.current !== 'export'"
class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Export your data')"
:disabled="status.current === 'import'"
@click.stop.prevent="startExport">
<template #icon>
<PackageDown decorative />
</template>
<template v-if="status.status === 'started'" #desc>
{{ t('user_migration', 'Please do not use your account while exporting.') }}
<PackageDown title="" :size="20" />
</template>
</EmptyContent>
<div v-if="status.status === 'waiting' || status.status === 'started'"
class="section__icon icon-loading" />
<CheckCircleOutline v-else
class="section__icon"
title=""
:size="40" />
{{ t('user_migration', 'Export') }}
</Button>
<div v-if="startingExport" class="icon-loading" />
</div>
</Modal>
<div v-else class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Show export status')"
:disabled="status.current === 'import'"
@click.stop.prevent="openModal">
{{ t('user_migration', 'Show status') }}
</Button>
<span class="settings-hint">{{ status.status === 'waiting' ? t('user_migration', 'Export queued') : t('user_migration', 'Export in progress…') }}</span>
</div>

<Modal v-if="modalOpened"
@close="closeModal">
<div class="section__modal">
<EmptyContent>
{{ modalMessage }}
<template #icon>
<PackageDown decorative />
</template>
<template v-if="status.status === 'started'" #desc>
{{ t('user_migration', 'Please do not use your account while exporting.') }}
</template>
</EmptyContent>
<div v-if="status.status === 'waiting' || status.status === 'started'"
class="section__icon icon-loading" />
<template v-else>
<CheckCircleOutline class="section__icon"
title=""
:size="40" />
<Button class="section__close"
type="secondary"
:aria-label="t('user_migration', 'Close export status')"
@click.stop.prevent="closeModal">
{{ t('user_migration', 'Close') }}
</Button>
</template>
</div>
</Modal>
</template>
<div v-else class="icon-loading" />
</div>
</template>

Expand Down Expand Up @@ -123,6 +133,10 @@ export default {
},

props: {
loading: {
type: Boolean,
default: true,
},
migrators: {
type: Array,
default: () => [],
Expand Down Expand Up @@ -150,10 +164,15 @@ export default {
}
return t('user_migration', 'Export completed successfully')
},
},

sortedMigrators() {
// TODO sort migrators?
return this.migrators
watch: {
migrators: {
deep: true,
immediate: true,
handler(migrators, oldMigrators) {
this.selectedMigrators = migrators.map(({ id }) => id)
},
},
},

Expand Down Expand Up @@ -213,15 +232,19 @@ export default {
}

.section__modal {
margin: 110px auto;
margin: 80px auto 60px auto;

&::v-deep .empty-content {
margin-top: 0;
}

.section__icon {
height: 40px;
margin-top: 20px;
margin: 20px 0;
}

.section__close {
margin: 40px auto 0 auto;
}
}
</style>
118 changes: 68 additions & 50 deletions src/components/ImportSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,57 +24,67 @@
<div class="section">
<h2>{{ t('user_migration', 'Import') }}</h2>

<h3 class="section__hint settings-hint">
{{ t('user_migration', 'Please note that existing data may be overwritten') }}
</h3>

<!-- TODO use server API -->

<div v-if="status.current !== 'import'"
class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Import your data')"
:disabled="status.current === 'export'"
@click.stop.prevent="pickImportFile">
<template #icon>
<PackageUp title="" :size="20" />
</template>
{{ t('user_migration', 'Import') }}
</Button>
<div v-if="startingImport" class="icon-loading" />
</div>
<div v-else class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Show import status')"
:disabled="status.current === 'export'"
@click.stop.prevent="openModal">
{{ t('user_migration', 'Show status') }}
</Button>
<span class="settings-hint">{{ status.status === 'waiting' ? t('user_migration', 'Import queued') : t('user_migration', 'Import in progress…') }}</span>
</div>

<span class="section__picker-error error">{{ filePickerError }}</span>

<Modal v-if="modalOpened"
@close="closeModal">
<div class="section__modal">
<EmptyContent>
{{ modalMessage }}
<template v-if="!loading">
<h3 class="section__hint settings-hint">
{{ t('user_migration', 'Please note that existing data may be overwritten') }}
</h3>

<!-- TODO use server API -->

<div v-if="status.current !== 'import'"
class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Import your data')"
:disabled="status.current === 'export'"
@click.stop.prevent="pickImportFile">
<template #icon>
<PackageUp decorative />
<PackageUp title="" :size="20" />
</template>
<template v-if="status.status === 'started'" #desc>
{{ t('user_migration', 'Please do not use your account while importing.') }}
</template>
</EmptyContent>
<div v-if="status.status === 'waiting' || status.status === 'started'"
class="section__icon icon-loading" />
<CheckCircleOutline v-else
class="section__icon"
title=""
:size="40" />
{{ t('user_migration', 'Import') }}
</Button>
<div v-if="startingImport" class="icon-loading" />
</div>
<div v-else class="section__status">
<Button type="secondary"
:aria-label="t('user_migration', 'Show import status')"
:disabled="status.current === 'export'"
@click.stop.prevent="openModal">
{{ t('user_migration', 'Show status') }}
</Button>
<span class="settings-hint">{{ status.status === 'waiting' ? t('user_migration', 'Import queued') : t('user_migration', 'Import in progress…') }}</span>
</div>
</Modal>

<span class="section__picker-error error">{{ filePickerError }}</span>

<Modal v-if="modalOpened"
@close="closeModal">
<div class="section__modal">
<EmptyContent>
{{ modalMessage }}
<template #icon>
<PackageUp decorative />
</template>
<template v-if="status.status === 'started'" #desc>
{{ t('user_migration', 'Please do not use your account while importing.') }}
</template>
</EmptyContent>
<div v-if="status.status === 'waiting' || status.status === 'started'"
class="section__icon icon-loading" />
<template v-else>
<CheckCircleOutline class="section__icon"
title=""
:size="40" />
<Button class="section__close"
type="secondary"
:aria-label="t('user_migration', 'Close import status')"
@click.stop.prevent="closeModal">
{{ t('user_migration', 'Close') }}
</Button>
</template>
</div>
</Modal>
</template>
<div v-else class="icon-loading" />
</div>
</template>

Expand Down Expand Up @@ -109,6 +119,10 @@ export default {
},

props: {
loading: {
type: Boolean,
default: true,
},
status: {
type: Object,
default: () => ({}),
Expand Down Expand Up @@ -198,15 +212,19 @@ export default {
}

.section__modal {
margin: 110px auto;
margin: 80px auto 60px auto;

&::v-deep .empty-content {
margin-top: 0;
}

.section__icon {
height: 40px;
margin-top: 20px;
margin: 20px 0;
}

.section__close {
margin: 40px auto 0 auto;
}
}
</style>
8 changes: 6 additions & 2 deletions src/views/Personal/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@

<template>
<section>
<ExportSection :status="status"
<ExportSection :loading="loading"
:migrators="migrators"
:status="status"
@refresh-status="onRefreshStatus" />
<ImportSection :status="status"
<ImportSection :loading="loading"
:status="status"
@refresh-status="onRefreshStatus" />
</section>
</template>
Expand All @@ -52,6 +54,7 @@ export default {

data() {
return {
loading: true,
migrators: [],
status: { current: null },
}
Expand All @@ -60,6 +63,7 @@ export default {
async created() {
await this.fetchMigrators()
await this.fetchStatus()
this.loading = false
setInterval(this.fetchStatus, STATUS_POLLING_INTERVAL * 1000)
},

Expand Down