Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Onboarding import facility - Mostly designs #9534

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b3d2542
Move syncTaskUtils into core as it's shared across SetupWizard, Facil…
nucleogenesis Jun 23, 2022
cb2b2c1
Import TaskTypes, TaskStatuses, TransferTypes from kolibri.utils.sync…
nucleogenesis Jun 23, 2022
b215043
Move FacilityTaskPanel(Details) to core & syncComponentSet
nucleogenesis Jun 23, 2022
2c5d6f2
update selectFacilityTitle message to "Select learning facility"
nucleogenesis Jun 23, 2022
a5c9f68
Preclude non-Boolean return type on SelectAddressForm#submitDisabled
nucleogenesis Jun 23, 2022
f53553b
Only render description prop <p> when there is a description to show
nucleogenesis Jun 23, 2022
0f5ae0d
ImportFacilitySetup: remove styling, add step & component ImportAuthe…
nucleogenesis Jun 23, 2022
1e736b2
ensure network address is selected before going to select a facility …
nucleogenesis Jun 23, 2022
ac156cb
SelectFacilityForm: remove all admin form business, emit data to pare…
nucleogenesis Jun 23, 2022
5fad68d
Wrap LoadingTaskPage with OnbStepBase, update title message, use core…
nucleogenesis Jun 23, 2022
3fc56c0
OnboardingStepBase listens for enter key, continues if focused elemen…
nucleogenesis Jun 24, 2022
479dacc
OnboardingStepBase navDisabled prop to permit disabling of back/conti…
nucleogenesis Jun 24, 2022
b883396
LoadingTaskPage disables nav when task is neither failed nor complete…
nucleogenesis Jun 24, 2022
4111c6b
SuperUserCredentialsForm header msg changed to "Create super admin" -…
nucleogenesis Jun 24, 2022
9c0a906
Ensure FacilityAdminCredentialsForm wrapped in <form> tags; remediate…
nucleogenesis Jun 24, 2022
9deda6e
skip LoadingTaskPage tests re: buttons - will update suite when flow …
nucleogenesis Jun 24, 2022
df54943
arrow func rather than bind
nucleogenesis Jul 20, 2022
41bcada
trap focus in language switcher modal
nucleogenesis Aug 3, 2022
dfaa167
focus doesn't get trapped when v-show already rendered it into the do…
nucleogenesis Aug 4, 2022
dfc402e
add new address button moved under address list, also fixes focus out…
nucleogenesis Aug 4, 2022
31051ce
use the new getTaskString export
nucleogenesis Aug 4, 2022
95afde2
ensure function not called until expected in sync status info, fix mi…
nucleogenesis Aug 4, 2022
6356f39
fix broken refs after rebase
nucleogenesis Aug 10, 2022
ad797f8
use extra_metadata field for facility name on task status string
nucleogenesis Aug 10, 2022
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
2 changes: 2 additions & 0 deletions kolibri/core/assets/src/core-app/apiSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import redirectBrowser from '../utils/redirectBrowser';
import * as licenseTranslations from '../utils/licenseTranslations';
import bytesForHumans from '../utils/bytesForHumans';
import UserType from '../utils/UserType';
import * as syncTaskUtils from '../utils/syncTaskUtils';
import samePageCheckGenerator from '../utils/samePageCheckGenerator';
import Backdrop from '../views/Backdrop';
import CoreSnackbar from '../views/CoreSnackbar';
Expand Down Expand Up @@ -245,6 +246,7 @@ export default {
serverClock,
shuffled,
sortLanguages,
syncTaskUtils,
UserType,
validators,
coreStrings,
Expand Down
2 changes: 1 addition & 1 deletion kolibri/core/assets/src/mixins/commonSyncElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const syncStrings = createTranslator('CommonSyncStrings', {
context: 'Label for a button that opens a menu to save a new network address.',
},
selectFacilityTitle: {
message: 'Select facility',
message: 'Select learning facility',
context:
'Title of the modal window where the user selects a facility to import from the source device, if there are multiple facilities available to import.',
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,45 @@
import coreStrings from 'kolibri.coreVue.mixins.commonCoreStrings';
import taskStrings from 'kolibri.coreVue.mixins.commonTaskStrings';
import bytesForHumans from 'kolibri.utils.bytesForHumans';
import { TaskStatuses, TaskTypes } from '../constants';
import commonCoreStrings from '../mixins/commonCoreStrings';
import { getTaskString } from '../mixins/taskStrings';
import bytesForHumans from '../utils/bytesForHumans';

export const TaskTypes = {
REMOTECHANNELIMPORT: 'kolibri.core.content.tasks.remotechannelimport',
REMOTECONTENTIMPORT: 'kolibri.core.content.tasks.remotecontentimport',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not blocking: This is a bit nit-picky, and I can see that this was just a "move existing code" but if it's possible, would we have these be more like REMOTE_CHANNEL_IMPORT without it being too much of a hassle? I think it would be a lot easier to read. If easier to keep as is, because these are in too many places, no problem though

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯 no prob at all good idea

REMOTEIMPORT: 'kolibri.core.content.tasks.remoteimport',
DISKCHANNELIMPORT: 'kolibri.core.content.tasks.diskchannelimport',
DISKCONTENTIMPORT: 'kolibri.core.content.tasks.diskcontentimport',
DISKIMPORT: 'kolibri.core.content.tasks.diskimport',
DISKCONTENTEXPORT: 'kolibri.core.content.tasks.diskcontentexport',
DISKEXPORT: 'kolibri.core.content.tasks.diskexport',
DELETECHANNEL: 'kolibri.core.content.tasks.deletechannel',
UPDATECHANNEL: 'kolibri.core.content.tasks.updatechannel',
REMOTECHANNELDIFFSTATS: 'kolibri.core.content.tasks.remotechanneldiffstats',
LOCALCHANNELDIFFSTATS: 'kolibri.core.content.tasks.localchanneldiffstats',
SYNCDATAPORTAL: 'kolibri.core.auth.tasks.dataportalsync',
SYNCPEERFULL: 'kolibri.core.auth.tasks.peerfacilitysync',
SYNCPEERPULL: 'kolibri.core.auth.tasks.peerfacilityimport',
DELETEFACILITY: 'kolibri.core.auth.tasks.deletefacility',
};

// identical to facility constants.js
export const TaskStatuses = Object.freeze({
IN_PROGRESS: 'INPROGRESS',
COMPLETED: 'COMPLETED',
FAILED: 'FAILED',
PENDING: 'PENDING',
RUNNING: 'RUNNING',
QUEUED: 'QUEUED',
SCHEDULED: 'SCHEDULED',
CANCELED: 'CANCELED',
CANCELING: 'CANCELING',
});

export const TransferTypes = {
LOCALEXPORT: 'localexport',
LOCALIMPORT: 'localimport',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

PEERIMPORT: 'peerimport',
REMOTEIMPORT: 'remoteimport',
};

export const SyncTaskStatuses = {
SESSION_CREATION: 'SESSION_CREATION',
Expand All @@ -18,8 +56,7 @@ export const SyncTaskStatuses = {
FAILED: 'FAILED',
};

const { getTaskString } = taskStrings.methods;
const { coreString } = coreStrings.methods;
const { coreString } = commonCoreStrings.methods;

const syncTaskStatusToStepMap = {
[SyncTaskStatuses.SESSION_CREATION]: 1,
Expand All @@ -31,24 +68,25 @@ const syncTaskStatusToStepMap = {
[SyncTaskStatuses.REMOTE_DEQUEUING]: 7,
};

// getTaskString is wrapped in an arrow func to avoid evaluation before i18n is ready
const genericStatusToDescriptionMap = {
[TaskStatuses.PENDING]: getTaskString('taskWaitingStatus'),
[TaskStatuses.QUEUED]: getTaskString('taskWaitingStatus'),
[TaskStatuses.COMPLETED]: getTaskString('taskFinishedStatus'),
[TaskStatuses.CANCELED]: getTaskString('taskCanceledStatus'),
[TaskStatuses.CANCELING]: getTaskString('taskCancelingStatus'),
[TaskStatuses.FAILED]: getTaskString('taskFailedStatus'),
[TaskStatuses.PENDING]: () => getTaskString('taskWaitingStatus'),
[TaskStatuses.QUEUED]: () => getTaskString('taskWaitingStatus'),
[TaskStatuses.COMPLETED]: () => getTaskString('taskFinishedStatus'),
[TaskStatuses.CANCELED]: () => getTaskString('taskCanceledStatus'),
[TaskStatuses.CANCELING]: () => getTaskString('taskCancelingStatus'),
[TaskStatuses.FAILED]: () => getTaskString('taskFailedStatus'),
};

export const syncStatusToDescriptionMap = {
...genericStatusToDescriptionMap,
[SyncTaskStatuses.SESSION_CREATION]: getTaskString('establishingConnectionStatus'),
[SyncTaskStatuses.REMOTE_QUEUING]: getTaskString('remotelyPreparingDataStatus'),
[SyncTaskStatuses.PULLING]: getTaskString('receivingDataStatus'),
[SyncTaskStatuses.LOCAL_DEQUEUING]: getTaskString('locallyIntegratingDataStatus'),
[SyncTaskStatuses.LOCAL_QUEUING]: getTaskString('locallyPreparingDataStatus'),
[SyncTaskStatuses.PUSHING]: getTaskString('sendingDataStatus'),
[SyncTaskStatuses.REMOTE_DEQUEUING]: getTaskString('remotelyIntegratingDataStatus'),
[SyncTaskStatuses.SESSION_CREATION]: () => getTaskString('establishingConnectionStatus'),
[SyncTaskStatuses.REMOTE_QUEUING]: () => getTaskString('remotelyPreparingDataStatus'),
[SyncTaskStatuses.PULLING]: () => getTaskString('receivingDataStatus'),
[SyncTaskStatuses.LOCAL_DEQUEUING]: () => getTaskString('locallyIntegratingDataStatus'),
[SyncTaskStatuses.LOCAL_QUEUING]: () => getTaskString('locallyPreparingDataStatus'),
[SyncTaskStatuses.PUSHING]: () => getTaskString('sendingDataStatus'),
[SyncTaskStatuses.REMOTE_DEQUEUING]: () => getTaskString('remotelyIntegratingDataStatus'),
};

function formatNameWithId(name, id) {
Expand Down Expand Up @@ -85,20 +123,20 @@ export function syncFacilityTaskDisplayInfo(task) {
const statusDescription =
syncStatusToDescriptionMap[task.extra_metadata.sync_state] ||
syncStatusToDescriptionMap[task.status] ||
getTaskString('taskUnknownStatus');
(() => getTaskString('taskUnknownStatus'));

if (task.status === TaskStatuses.COMPLETED) {
statusMsg = getTaskString('taskFinishedStatus');
} else if (syncStep) {
statusMsg = getTaskString('syncStepAndDescription', {
step: syncStep,
total: task.type === TaskTypes.SYNCPEERPULL ? PULLSTEPS : PUSHPULLSTEPS,
description: statusDescription,
description: statusDescription(),
});
} else {
if (task.type === TaskTypes.SYNCLOD && task.status === TaskStatuses.FAILED)
statusMsg = `${statusDescription}: ${task.exception}`;
else statusMsg = statusDescription;
statusMsg = `${statusDescription()}: ${task.exception}`;
else statusMsg = statusDescription();
}

if (task.status === TaskStatuses.COMPLETED) {
Expand Down Expand Up @@ -127,7 +165,7 @@ export function syncFacilityTaskDisplayInfo(task) {

export const removeStatusToDescriptionMap = {
...genericStatusToDescriptionMap,
[TaskStatuses.RUNNING]: getTaskString('removingFacilityStatus'),
[TaskStatuses.RUNNING]: () => getTaskString('removingFacilityStatus'),
};

// Consolidates logic on how Remove-Facility Tasks should be displayed
Expand All @@ -137,7 +175,7 @@ export function removeFacilityTaskDisplayInfo(task) {
task.extra_metadata.facility
);
const statusDescription =
removeStatusToDescriptionMap[task.status] || getTaskString('taskUnknownStatus');
removeStatusToDescriptionMap[task.status]() || getTaskString('taskUnknownStatus');

return {
headingMsg: getTaskString('removeFacilityTaskLabel', { facilityName }),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
<template>

<KModal
:title="$tr('changeLanguageModalHeader')"
:submitText="coreString('confirmAction')"
:cancelText="coreString('cancelAction')"
:size="600"
@cancel="cancel"
@submit="setLang"
<FocusTrap
@shouldFocusFirstEl="focusFirstEl"
@shouldFocusLastEl="focusLastEl"
>
<KGrid>
<KGridItem
v-for="(languageCol, index) in splitLanguageOptions"
:key="index"
:class="{ 'offset-col': windowIsSmall && index === 1 }"
:layout8="{ span: 4 }"
:layout12="{ span: 6 }"
>
<KRadioButton
v-for="language in languageCol"
:key="language.id"
v-model="selectedLanguage"
:value="language.id"
:label="language.lang_name"
:title="language.english_name"
class="language-name"
/>
</KGridItem>
</KGrid>

</KModal>

<KModal
:title="$tr('changeLanguageModalHeader')"
:submitText="coreString('confirmAction')"
:cancelText="coreString('cancelAction')"
:size="600"
@cancel="cancel"
@submit="setLang"
>
<KGrid>
<KGridItem
v-for="(languageCol, index) in splitLanguageOptions"
:key="index"
:class="{ 'offset-col': windowIsSmall && index === 1 }"
:layout8="{ span: 4 }"
:layout12="{ span: 6 }"
>
<KRadioButton
v-for="language in languageCol"
:key="language.id"
ref="languageItem"
v-model="selectedLanguage"
:value="language.id"
:label="language.lang_name"
:title="language.english_name"
class="language-name"
/>
</KGridItem>
</KGrid>

</KModal>

</FocusTrap>

</template>

Expand All @@ -38,10 +46,12 @@
import { currentLanguage } from 'kolibri.utils.i18n';
import responsiveWindowMixin from 'kolibri.coreVue.mixins.responsiveWindowMixin';
import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings';
import FocusTrap from 'kolibri.coreVue.components.FocusTrap';
import languageSwitcherMixin from './mixin';

export default {
name: 'LanguageSwitcherModal',
components: { FocusTrap },
mixins: [commonCoreStrings, languageSwitcherMixin, responsiveWindowMixin],
data() {
return {
Expand All @@ -57,6 +67,12 @@
},
},
methods: {
focusFirstEl() {
this.$refs.languageItem[0].focus();
},
focusLastEl() {
this.$refs.languageItem[this.$refs.languageItem.length - 1].focus();
},
setLang() {
if (currentLanguage === this.selectedLanguage) {
this.cancel();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>

<div>
<form>
<p v-if="singleFacility && facility.name" class="facility-name">
{{ formatNameAndId(facility.name, facility.id) }}
</p>
Expand Down Expand Up @@ -31,7 +31,7 @@
:showConfirmationInput="false"
:disabled="$attrs.disabled"
/>
</div>
</form>

</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
syncFacilityTaskDisplayInfo,
removeFacilityTaskDisplayInfo,
importFacilityTaskDisplayInfo,
} from '../syncTaskUtils';
import { TaskTypes } from '../../constants';
TaskTypes,
} from '../../utils/syncTaskUtils';
import FacilityTaskPanelDetails from './FacilityTaskPanelDetails';

const indeterminateSyncStatuses = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
import responsiveWindowMixin from 'kolibri.coreVue.mixins.responsiveWindowMixin';
import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings';
import commonTaskStrings from 'kolibri.coreVue.mixins.commonTaskStrings';
import { TaskStatuses, TaskTypes } from '../../constants';
import { TaskStatuses, TaskTypes } from '../../utils/syncTaskUtils';

export default {
name: 'FacilityTaskPanelDetails',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@
/>
</UiAlert>

<KButton
v-show="!newAddressButtonDisabled && !formDisabled"
class="new-address-button"
:text="$tr('newAddressButtonLabel')"
appearance="basic-link"
@click="$emit('click_add_address')"
/>

<!-- Static Addresses -->
<template v-for="(a, idx) in savedAddresses">
<div :key="`div-${idx}`">
Expand Down Expand Up @@ -115,6 +107,15 @@
</KFixedGrid>
</template>

<KButton
v-show="!newAddressButtonDisabled && !formDisabled"
class="new-address-button"
:text="$tr('newAddressButtonLabel')"
appearance="basic-link"
@click="$emit('click_add_address')"
/>


</KModal>

</template>
Expand Down Expand Up @@ -231,12 +232,12 @@
};
},
submitDisabled() {
return (
return Boolean(
this.selectedAddressId === '' ||
this.fetchingAddresses & !this.filterLODAvailable ||
this.deletingAddress ||
this.discoveryFailed ||
this.availableAddressIds.length === 0
this.fetchingAddresses & !this.filterLODAvailable ||
this.deletingAddress ||
this.discoveryFailed ||
this.availableAddressIds.length === 0
);
},
newAddressButtonDisabled() {
Expand Down Expand Up @@ -361,7 +362,7 @@
<style lang="scss" scoped>

.new-address-button {
margin-bottom: 16px;
margin: 0 0 1em;
}

.radio-button {
Expand Down
1 change: 1 addition & 0 deletions kolibri/core/assets/src/views/sync/syncComponentSet.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { default as SelectAddressForm } from './SelectAddressModalGroup/SelectAddressForm';
export { default as SelectAddressModalGroup } from './SelectAddressModalGroup';
export { default as FacilityTaskPanel } from './FacilityTaskPanel';
export { default as ConfirmationRegisterModal } from './ConfirmationRegisterModal';
export { default as FacilityAdminCredentialsForm } from './FacilityAdminCredentialsForm';
export { default as FacilityNameAndSyncStatus } from './FacilityNameAndSyncStatus/index';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import {
removeStatusToDescriptionMap,
removeFacilityTaskDisplayInfo,
SyncTaskStatuses,
} from '../syncTaskUtils';
import { TaskStatuses, TaskTypes } from '../../constants';
TaskStatuses,
TaskTypes,
} from '../../src/utils/syncTaskUtils';

const CLEARABLE_STATUSES = ['COMPLETED', 'CANCELED', 'FAILED'];

Expand Down
Loading