@northern.tech/store 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +9 -0
- package/.prettierignore +1 -0
- package/CHANGELOG.md +12 -0
- package/actions.ts +32 -0
- package/api/general-api.test.ts +51 -0
- package/api/general-api.ts +60 -0
- package/api/types/AWSCredentials.ts +16 -0
- package/api/types/Actor.ts +35 -0
- package/api/types/Addon.ts +17 -0
- package/api/types/AddonTenantadm.ts +17 -0
- package/api/types/Alert.ts +34 -0
- package/api/types/AlertDetails.ts +23 -0
- package/api/types/AlertSubject.ts +23 -0
- package/api/types/ApiBurst.ts +21 -0
- package/api/types/ApiBurstTenantadm.ts +21 -0
- package/api/types/ApiLimits.ts +16 -0
- package/api/types/ApiLimitsTenantadm.ts +16 -0
- package/api/types/ApiQuota.ts +17 -0
- package/api/types/ApiQuotaTenantadm.ts +17 -0
- package/api/types/Artifact.ts +48 -0
- package/api/types/ArtifactDeployments.ts +48 -0
- package/api/types/ArtifactInfo.ts +11 -0
- package/api/types/ArtifactInfoDeployments.ts +11 -0
- package/api/types/ArtifactLink.ts +11 -0
- package/api/types/ArtifactTypeInfo.ts +13 -0
- package/api/types/ArtifactTypeInfoDeployments.ts +13 -0
- package/api/types/ArtifactUpdate.ts +10 -0
- package/api/types/ArtifactUploadLink.ts +15 -0
- package/api/types/Attribute.ts +36 -0
- package/api/types/AttributeInventory.ts +32 -0
- package/api/types/AuditLog.ts +26 -0
- package/api/types/AuthSet.ts +33 -0
- package/api/types/AuthSetDeviceauth.ts +37 -0
- package/api/types/AutoAuthRequest.ts +23 -0
- package/api/types/AzureSharedAccessSecret.ts +11 -0
- package/api/types/BillingInfo.ts +13 -0
- package/api/types/BinaryDeltaConfiguration.ts +15 -0
- package/api/types/BinaryDeltaConfigurationDeployments.ts +15 -0
- package/api/types/BinaryDeltaLimits.ts +15 -0
- package/api/types/BinaryDeltaLimitsDeployments.ts +15 -0
- package/api/types/BoundingBox.ts +11 -0
- package/api/types/CancelRequest.ts +10 -0
- package/api/types/CardData.ts +49 -0
- package/api/types/CardSetupData.ts +17 -0
- package/api/types/CheckoutData.ts +13 -0
- package/api/types/Configuration.ts +11 -0
- package/api/types/Count.ts +13 -0
- package/api/types/Credentials.ts +23 -0
- package/api/types/DBusSubsystem.ts +27 -0
- package/api/types/DeltaConfiguration.ts +14 -0
- package/api/types/DeltaConfigurationDeployments.ts +14 -0
- package/api/types/Deployment.ts +95 -0
- package/api/types/DeploymentAggregation.ts +18 -0
- package/api/types/DeploymentAggregationItem.ts +18 -0
- package/api/types/DeploymentAggregationTerm.ts +23 -0
- package/api/types/DeploymentAggregationTerms.ts +18 -0
- package/api/types/DeploymentAttributeProjection.ts +11 -0
- package/api/types/DeploymentAuditlogs.ts +11 -0
- package/api/types/DeploymentDeployments.ts +99 -0
- package/api/types/DeploymentFilterTerm.ts +37 -0
- package/api/types/DeploymentIdentifier.ts +10 -0
- package/api/types/DeploymentPhase.ts +23 -0
- package/api/types/DeploymentReporting.ts +46 -0
- package/api/types/DeploymentSearchTerms.ts +39 -0
- package/api/types/DeploymentSortTerm.ts +25 -0
- package/api/types/DeploymentStatistics.ts +15 -0
- package/api/types/DeploymentStatusStatistics.ts +54 -0
- package/api/types/Device.ts +29 -0
- package/api/types/DeviceAggregation.ts +18 -0
- package/api/types/DeviceAggregationItem.ts +18 -0
- package/api/types/DeviceAggregationTerm.ts +27 -0
- package/api/types/DeviceAggregationTerms.ts +22 -0
- package/api/types/DeviceAttribute.ts +23 -0
- package/api/types/DeviceAttributeProjection.ts +15 -0
- package/api/types/DeviceAuditlogs.ts +17 -0
- package/api/types/DeviceAuthEvent.ts +23 -0
- package/api/types/DeviceConfiguration.ts +16 -0
- package/api/types/DeviceDeployment.ts +11 -0
- package/api/types/DeviceDeployments.ts +31 -0
- package/api/types/DeviceDeviceauth.ts +42 -0
- package/api/types/DeviceFilterAttribute.ts +22 -0
- package/api/types/DeviceFilterTerm.ts +41 -0
- package/api/types/DeviceInventory.ts +19 -0
- package/api/types/DeviceInventoryInventory.ts +19 -0
- package/api/types/DeviceReporting.ts +22 -0
- package/api/types/DeviceSearchTerms.ts +39 -0
- package/api/types/DeviceSortTerm.ts +29 -0
- package/api/types/DeviceState.ts +32 -0
- package/api/types/DeviceStateDeviceconnect.ts +33 -0
- package/api/types/DeviceStateIot_manager.ts +14 -0
- package/api/types/DeviceStatus.ts +19 -0
- package/api/types/DeviceWithImage.ts +80 -0
- package/api/types/DirectUploadMetadata.ts +18 -0
- package/api/types/EmailVerificationCompletion.ts +13 -0
- package/api/types/EmailVerificationRequest.ts +13 -0
- package/api/types/Error.ts +17 -0
- package/api/types/ErrorAuditlogs.ts +13 -0
- package/api/types/ErrorDeployments.ts +17 -0
- package/api/types/ErrorDeviceauth.ts +13 -0
- package/api/types/ErrorDeviceconfig.ts +17 -0
- package/api/types/ErrorDeviceconnect.ts +17 -0
- package/api/types/ErrorDevicemonitor.ts +17 -0
- package/api/types/ErrorExt.ts +18 -0
- package/api/types/ErrorInventory.ts +17 -0
- package/api/types/ErrorIot_manager.ts +17 -0
- package/api/types/ErrorNotFound.ts +17 -0
- package/api/types/ErrorReporting.ts +18 -0
- package/api/types/ErrorTenantadm.ts +13 -0
- package/api/types/ErrorUseradm.ts +17 -0
- package/api/types/Event.ts +48 -0
- package/api/types/ExternalIdentity.ts +17 -0
- package/api/types/Features.ts +17 -0
- package/api/types/FileUpload.ts +23 -0
- package/api/types/Filter.ts +19 -0
- package/api/types/FilterAttribute.ts +21 -0
- package/api/types/FilterDefinition.ts +18 -0
- package/api/types/FilterDeployments.ts +19 -0
- package/api/types/FilterInventory.ts +20 -0
- package/api/types/FilterPredicate.ts +78 -0
- package/api/types/FilterPredicateDeployments.ts +48 -0
- package/api/types/FilterPredicateInventory.ts +76 -0
- package/api/types/GeoBoundingBox.ts +10 -0
- package/api/types/GeoBoundingBoxFilter.ts +6 -0
- package/api/types/GeoDistance.ts +17 -0
- package/api/types/GeoDistanceFilter.ts +10 -0
- package/api/types/GeoPoint.ts +15 -0
- package/api/types/Group.ts +10 -0
- package/api/types/HTTP.ts +19 -0
- package/api/types/IdentityData.ts +25 -0
- package/api/types/InputParameter.ts +8 -0
- package/api/types/Integration.ts +24 -0
- package/api/types/JobStatus.ts +13 -0
- package/api/types/Limit.ts +21 -0
- package/api/types/LimitDeployments.ts +21 -0
- package/api/types/LimitDeviceauth.ts +10 -0
- package/api/types/LimitUseradm.ts +11 -0
- package/api/types/Limits.ts +11 -0
- package/api/types/LineDescriptor.ts +11 -0
- package/api/types/LogSubsystem.ts +23 -0
- package/api/types/LoginOptions.ts +18 -0
- package/api/types/ManagementAPIConfiguration.ts +5 -0
- package/api/types/MenderTypes.ts +183 -0
- package/api/types/MonitorConfiguration.ts +22 -0
- package/api/types/NewConfigurationDeployment.ts +15 -0
- package/api/types/NewConfigurationDeploymentResponse.ts +10 -0
- package/api/types/NewDeployment.ts +42 -0
- package/api/types/NewDeploymentForGroup.ts +33 -0
- package/api/types/NewDeploymentPhase.ts +37 -0
- package/api/types/NewDeploymentPhaseDeployments.ts +20 -0
- package/api/types/NewDeploymentV2.ts +31 -0
- package/api/types/NewTenant.ts +41 -0
- package/api/types/Object.ts +35 -0
- package/api/types/OwnUserUpdate.ts +21 -0
- package/api/types/PasswordResetCompletion.ts +17 -0
- package/api/types/PasswordResetRequest.ts +13 -0
- package/api/types/Permission.ts +21 -0
- package/api/types/PermissionObject.ts +14 -0
- package/api/types/PermissionSet.ts +22 -0
- package/api/types/PermissionSetWithScope.ts +15 -0
- package/api/types/PersonalAccessToken.ts +29 -0
- package/api/types/PersonalAccessTokenRequest.ts +18 -0
- package/api/types/Plan.ts +19 -0
- package/api/types/PlanBindingDetails.ts +13 -0
- package/api/types/PlanChangeRequest.ts +14 -0
- package/api/types/PlanLimits.ts +12 -0
- package/api/types/PreAuthSet.ts +16 -0
- package/api/types/Release.ts +32 -0
- package/api/types/ReleaseDeployments.ts +32 -0
- package/api/types/ReleaseUpdate.ts +13 -0
- package/api/types/Releases.ts +9 -0
- package/api/types/ReleasesDeleteError.ts +21 -0
- package/api/types/ReleasesDeployments.ts +9 -0
- package/api/types/Role.ts +19 -0
- package/api/types/RolePermission.ts +25 -0
- package/api/types/RolePermissionObject.ts +17 -0
- package/api/types/RoleUseradm.ts +19 -0
- package/api/types/SAMLMetadata.ts +21 -0
- package/api/types/Scope.ts +19 -0
- package/api/types/SelectAttribute.ts +17 -0
- package/api/types/ServiceSubsystem.ts +19 -0
- package/api/types/Settings.ts +23 -0
- package/api/types/SortCriteria.ts +30 -0
- package/api/types/SsoObject.ts +21 -0
- package/api/types/Status.ts +17 -0
- package/api/types/StatusDeviceauth.ts +18 -0
- package/api/types/StatusTenantadm.ts +19 -0
- package/api/types/StorageLimit.ts +17 -0
- package/api/types/SubscriptionData.ts +8 -0
- package/api/types/SupportRequest.ts +17 -0
- package/api/types/Tag.ts +27 -0
- package/api/types/Tags.ts +10 -0
- package/api/types/TaskResult.ts +13 -0
- package/api/types/TaskResultCLI.ts +10 -0
- package/api/types/TaskResultHTTPRequest.ts +8 -0
- package/api/types/TaskResultHTTPResponse.ts +10 -0
- package/api/types/Tenant.ts +38 -0
- package/api/types/TenantApiLimits.ts +12 -0
- package/api/types/TenantApiLimitsTenantadm.ts +12 -0
- package/api/types/TenantIdName.ts +14 -0
- package/api/types/TenantIdsData.ts +10 -0
- package/api/types/TenantInfo.ts +14 -0
- package/api/types/TenantShortInfo.ts +21 -0
- package/api/types/TenantTenantadm.ts +38 -0
- package/api/types/TenantsIdName.ts +6 -0
- package/api/types/Update.ts +17 -0
- package/api/types/UpdateDeployments.ts +18 -0
- package/api/types/UpdateFile.ts +13 -0
- package/api/types/UpdateFileDeployments.ts +13 -0
- package/api/types/UpdateTypes.ts +8 -0
- package/api/types/UpgradeCompleteRequest.ts +23 -0
- package/api/types/User.ts +13 -0
- package/api/types/UserAuditlogs.ts +13 -0
- package/api/types/UserNew.ts +26 -0
- package/api/types/UserUpdate.ts +25 -0
- package/api/types/UserUseradm.ts +45 -0
- package/api/types/UserWithTenantInfo.ts +8 -0
- package/api/types/XDeltaArgs.ts +9 -0
- package/api/types/XDeltaArgsDeployments.ts +9 -0
- package/api/types/XDeltaArgsLimits.ts +10 -0
- package/api/types/XDeltaArgsLimitsDeployments.ts +10 -0
- package/api/users-api.ts +34 -0
- package/appSlice/constants.ts +166 -0
- package/appSlice/index.ts +159 -0
- package/appSlice/reducer.test.ts +97 -0
- package/appSlice/selectors.ts +33 -0
- package/appSlice/thunks.test.ts +118 -0
- package/appSlice/thunks.ts +148 -0
- package/auth.test.ts +36 -0
- package/auth.ts +82 -0
- package/commonConstants.tsx +252 -0
- package/commonSelectors.ts +255 -0
- package/constants.ts +22 -0
- package/deploymentsSlice/constants.ts +175 -0
- package/deploymentsSlice/index.ts +145 -0
- package/deploymentsSlice/reducer.test.ts +108 -0
- package/deploymentsSlice/selectors.ts +58 -0
- package/deploymentsSlice/thunks.test.ts +425 -0
- package/deploymentsSlice/thunks.ts +382 -0
- package/devicesSlice/constants.ts +56 -0
- package/devicesSlice/index.ts +207 -0
- package/devicesSlice/reducer.test.ts +194 -0
- package/devicesSlice/selectors.ts +127 -0
- package/devicesSlice/thunks.test.tsx +1245 -0
- package/devicesSlice/thunks.tsx +1098 -0
- package/monitorSlice/constants.ts +17 -0
- package/monitorSlice/index.ts +65 -0
- package/monitorSlice/reducer.test.ts +79 -0
- package/monitorSlice/selectors.ts +15 -0
- package/monitorSlice/thunks.test.ts +112 -0
- package/monitorSlice/thunks.ts +101 -0
- package/onboardingSlice/constants.ts +53 -0
- package/onboardingSlice/index.ts +60 -0
- package/onboardingSlice/reducer.test.ts +45 -0
- package/onboardingSlice/selectors.ts +15 -0
- package/onboardingSlice/thunks.test.ts +235 -0
- package/onboardingSlice/thunks.ts +142 -0
- package/organizationSlice/constants.ts +82 -0
- package/organizationSlice/index.ts +111 -0
- package/organizationSlice/reducer.test.ts +78 -0
- package/organizationSlice/selectors.ts +45 -0
- package/organizationSlice/thunks.test.ts +619 -0
- package/organizationSlice/thunks.ts +383 -0
- package/package.json +38 -0
- package/releasesSlice/constants.ts +18 -0
- package/releasesSlice/index.ts +116 -0
- package/releasesSlice/reducer.test.ts +78 -0
- package/releasesSlice/selectors.ts +33 -0
- package/releasesSlice/thunks.test.ts +389 -0
- package/releasesSlice/thunks.ts +379 -0
- package/selectors.ts +22 -0
- package/store.ts +89 -0
- package/storehooks.test.tsx +386 -0
- package/storehooks.ts +250 -0
- package/thunks.ts +21 -0
- package/tsconfig.json +11 -0
- package/tsup.config.ts +11 -0
- package/usersSlice/constants.ts +374 -0
- package/usersSlice/index.ts +151 -0
- package/usersSlice/reducer.test.ts +141 -0
- package/usersSlice/selectors.ts +60 -0
- package/usersSlice/thunks.test.ts +660 -0
- package/usersSlice/thunks.ts +773 -0
- package/utils.test.ts +187 -0
- package/utils.ts +249 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// Copyright 2020 Northern.tech AS
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// @ts-nocheck
|
|
15
|
+
import { getUserSettings, saveUserSettings } from '@northern.tech/store/thunks';
|
|
16
|
+
import configureMockStore from 'redux-mock-store';
|
|
17
|
+
import { thunk } from 'redux-thunk';
|
|
18
|
+
|
|
19
|
+
import { actions } from '.';
|
|
20
|
+
import { defaultState } from '../../../../tests/mockData';
|
|
21
|
+
import { actions as userActions } from '../usersSlice';
|
|
22
|
+
import { onboardingSteps } from './constants';
|
|
23
|
+
import { advanceOnboarding, getOnboardingState, setOnboardingApproach, setOnboardingCanceled, setOnboardingComplete, setOnboardingDeviceType } from './thunks';
|
|
24
|
+
|
|
25
|
+
const middlewares = [thunk];
|
|
26
|
+
const mockStore = configureMockStore(middlewares);
|
|
27
|
+
|
|
28
|
+
export const defaultOnboardingState = {
|
|
29
|
+
approach: null,
|
|
30
|
+
complete: false,
|
|
31
|
+
demoArtifactPort: 85,
|
|
32
|
+
deviceType: null,
|
|
33
|
+
progress: undefined,
|
|
34
|
+
showConnectDeviceDialog: false,
|
|
35
|
+
showTips: undefined,
|
|
36
|
+
showTipsDialog: false,
|
|
37
|
+
something: 'here'
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const expectedOnboardingActions = [
|
|
41
|
+
{ type: getOnboardingState.pending.type },
|
|
42
|
+
{ type: actions.setOnboardingComplete.type, payload: false },
|
|
43
|
+
{
|
|
44
|
+
type: actions.setOnboardingState.type,
|
|
45
|
+
payload: {
|
|
46
|
+
...defaultOnboardingState,
|
|
47
|
+
address: 'http://192.168.10.141:85',
|
|
48
|
+
approach: 'physical',
|
|
49
|
+
deviceType: ['raspberrypi4'],
|
|
50
|
+
progress: 'devices-accepted-onboarding',
|
|
51
|
+
showTips: true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{ type: saveUserSettings.pending.type },
|
|
55
|
+
{ type: getUserSettings.pending.type },
|
|
56
|
+
{ type: userActions.setUserSettings.type, payload: { ...defaultState.users.userSettings } },
|
|
57
|
+
{ type: getUserSettings.fulfilled.type },
|
|
58
|
+
{
|
|
59
|
+
type: userActions.setUserSettings.type,
|
|
60
|
+
payload: {
|
|
61
|
+
...defaultState.users.userSettings,
|
|
62
|
+
onboarding: {
|
|
63
|
+
...defaultOnboardingState,
|
|
64
|
+
address: 'http://192.168.10.141:85',
|
|
65
|
+
approach: 'physical',
|
|
66
|
+
deviceType: ['raspberrypi4'],
|
|
67
|
+
progress: 'devices-accepted-onboarding',
|
|
68
|
+
showTips: true
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{ type: saveUserSettings.fulfilled.type },
|
|
73
|
+
{ type: getOnboardingState.fulfilled.type }
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
describe('onboarding actions', () => {
|
|
77
|
+
it('should pass on onboarding completion', async () => {
|
|
78
|
+
const store = mockStore({ ...defaultState });
|
|
79
|
+
await store.dispatch(setOnboardingComplete(true));
|
|
80
|
+
const expectedActions = [
|
|
81
|
+
{ type: setOnboardingComplete.pending.type },
|
|
82
|
+
{ type: actions.setOnboardingComplete.type, payload: true },
|
|
83
|
+
{ type: actions.setShowOnboardingHelp.type, payload: false },
|
|
84
|
+
{ type: advanceOnboarding.pending.type },
|
|
85
|
+
{ type: actions.setOnboardingProgress.type, payload: onboardingSteps.DEPLOYMENTS_PAST_COMPLETED_FAILURE },
|
|
86
|
+
{ type: saveUserSettings.pending.type },
|
|
87
|
+
{ type: getUserSettings.pending.type },
|
|
88
|
+
{ type: userActions.setUserSettings.type, payload: { ...defaultState.users.userSettings } },
|
|
89
|
+
{ type: getUserSettings.fulfilled.type },
|
|
90
|
+
{
|
|
91
|
+
type: userActions.setUserSettings.type,
|
|
92
|
+
payload: {
|
|
93
|
+
...defaultState.users.userSettings,
|
|
94
|
+
onboarding: {
|
|
95
|
+
...defaultOnboardingState,
|
|
96
|
+
complete: true,
|
|
97
|
+
progress: onboardingSteps.DEPLOYMENTS_PAST_COMPLETED_FAILURE
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{ type: saveUserSettings.fulfilled.type },
|
|
102
|
+
{ type: advanceOnboarding.fulfilled.type },
|
|
103
|
+
{ type: setOnboardingComplete.fulfilled.type }
|
|
104
|
+
];
|
|
105
|
+
const storeActions = store.getActions();
|
|
106
|
+
expect(storeActions.length).toEqual(expectedActions.length);
|
|
107
|
+
expectedActions.map((action, index) => Object.keys(action).map(key => expect(storeActions[index][key]).toEqual(action[key])));
|
|
108
|
+
});
|
|
109
|
+
it('should pass on onboarding approach', async () => {
|
|
110
|
+
const store = mockStore({ ...defaultState });
|
|
111
|
+
await store.dispatch(setOnboardingApproach('test'));
|
|
112
|
+
const expectedActions = [
|
|
113
|
+
{ type: setOnboardingApproach.pending.type },
|
|
114
|
+
{ type: actions.setOnboardingApproach.type, payload: 'test' },
|
|
115
|
+
{ type: saveUserSettings.pending.type },
|
|
116
|
+
{ type: getUserSettings.pending.type },
|
|
117
|
+
{ type: userActions.setUserSettings.type, payload: { ...defaultState.users.userSettings } },
|
|
118
|
+
{ type: getUserSettings.fulfilled.type },
|
|
119
|
+
{
|
|
120
|
+
type: userActions.setUserSettings.type,
|
|
121
|
+
payload: {
|
|
122
|
+
...defaultState.users.userSettings,
|
|
123
|
+
onboarding: {
|
|
124
|
+
...defaultOnboardingState,
|
|
125
|
+
approach: 'test'
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{ type: saveUserSettings.fulfilled.type },
|
|
130
|
+
{ type: setOnboardingApproach.fulfilled.type }
|
|
131
|
+
];
|
|
132
|
+
const storeActions = store.getActions();
|
|
133
|
+
expect(storeActions.length).toEqual(expectedActions.length);
|
|
134
|
+
expectedActions.map((action, index) => Object.keys(action).map(key => expect(storeActions[index][key]).toEqual(action[key])));
|
|
135
|
+
});
|
|
136
|
+
it('should pass on onboarding device type', async () => {
|
|
137
|
+
const store = mockStore({ ...defaultState });
|
|
138
|
+
await store.dispatch(setOnboardingDeviceType('testtype'));
|
|
139
|
+
const expectedActions = [
|
|
140
|
+
{ type: setOnboardingDeviceType.pending.type },
|
|
141
|
+
{ type: actions.setOnboardingDeviceType.type, payload: 'testtype' },
|
|
142
|
+
{ type: saveUserSettings.pending.type },
|
|
143
|
+
{ type: getUserSettings.pending.type },
|
|
144
|
+
{ type: userActions.setUserSettings.type, payload: { ...defaultState.users.userSettings } },
|
|
145
|
+
{ type: getUserSettings.fulfilled.type },
|
|
146
|
+
{
|
|
147
|
+
type: userActions.setUserSettings.type,
|
|
148
|
+
payload: {
|
|
149
|
+
...defaultState.users.userSettings,
|
|
150
|
+
columnSelection: [],
|
|
151
|
+
onboarding: {
|
|
152
|
+
...defaultOnboardingState,
|
|
153
|
+
deviceType: 'testtype'
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
{ type: saveUserSettings.fulfilled.type },
|
|
158
|
+
{ type: setOnboardingDeviceType.fulfilled.type }
|
|
159
|
+
];
|
|
160
|
+
const storeActions = store.getActions();
|
|
161
|
+
expect(storeActions.length).toEqual(expectedActions.length);
|
|
162
|
+
expectedActions.map((action, index) => Object.keys(action).map(key => expect(storeActions[index][key]).toEqual(action[key])));
|
|
163
|
+
});
|
|
164
|
+
it('should advance onboarding by one step', async () => {
|
|
165
|
+
const store = mockStore({ ...defaultState });
|
|
166
|
+
await store.dispatch(advanceOnboarding(onboardingSteps.DASHBOARD_ONBOARDING_START));
|
|
167
|
+
const expectedActions = [
|
|
168
|
+
{ type: advanceOnboarding.pending.type },
|
|
169
|
+
{ type: actions.setOnboardingProgress.type, payload: onboardingSteps.DEVICES_PENDING_ONBOARDING_START },
|
|
170
|
+
{ type: saveUserSettings.pending.type },
|
|
171
|
+
{ type: getUserSettings.pending.type },
|
|
172
|
+
{ type: userActions.setUserSettings.type, payload: { ...defaultState.users.userSettings } },
|
|
173
|
+
{ type: getUserSettings.fulfilled.type },
|
|
174
|
+
{
|
|
175
|
+
type: userActions.setUserSettings.type,
|
|
176
|
+
payload: {
|
|
177
|
+
...defaultState.users.userSettings,
|
|
178
|
+
columnSelection: [],
|
|
179
|
+
onboarding: {
|
|
180
|
+
...defaultOnboardingState,
|
|
181
|
+
progress: onboardingSteps.DEVICES_PENDING_ONBOARDING_START
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
{ type: saveUserSettings.fulfilled.type },
|
|
186
|
+
{ type: advanceOnboarding.fulfilled.type }
|
|
187
|
+
];
|
|
188
|
+
const storeActions = store.getActions();
|
|
189
|
+
expect(storeActions.length).toEqual(expectedActions.length);
|
|
190
|
+
expectedActions.map((action, index) => Object.keys(action).map(key => expect(storeActions[index][key]).toEqual(action[key])));
|
|
191
|
+
});
|
|
192
|
+
it('should disable helptips and store a canceled state', async () => {
|
|
193
|
+
const store = mockStore({ ...defaultState });
|
|
194
|
+
await store.dispatch(setOnboardingCanceled());
|
|
195
|
+
const expectedActions = [
|
|
196
|
+
{ type: setOnboardingCanceled.pending.type },
|
|
197
|
+
{ type: actions.setShowOnboardingHelp.type, payload: false },
|
|
198
|
+
{ type: actions.setShowDismissOnboardingTipsDialog.type, payload: false },
|
|
199
|
+
{ type: actions.setOnboardingComplete.type, payload: true },
|
|
200
|
+
{ type: advanceOnboarding.pending.type },
|
|
201
|
+
{ type: actions.setOnboardingProgress.type, payload: 'onboarding-canceled' },
|
|
202
|
+
{ type: saveUserSettings.pending.type },
|
|
203
|
+
{ type: getUserSettings.pending.type },
|
|
204
|
+
{ type: userActions.setUserSettings.type, payload: { ...defaultState.users.userSettings } },
|
|
205
|
+
{ type: getUserSettings.fulfilled.type },
|
|
206
|
+
{
|
|
207
|
+
type: userActions.setUserSettings.type,
|
|
208
|
+
payload: {
|
|
209
|
+
...defaultState.users.userSettings,
|
|
210
|
+
columnSelection: [],
|
|
211
|
+
onboarding: {
|
|
212
|
+
...defaultOnboardingState,
|
|
213
|
+
complete: true,
|
|
214
|
+
progress: 'onboarding-canceled'
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
{ type: saveUserSettings.fulfilled.type },
|
|
219
|
+
{ type: advanceOnboarding.fulfilled.type },
|
|
220
|
+
{ type: setOnboardingCanceled.fulfilled.type }
|
|
221
|
+
];
|
|
222
|
+
const storeActions = store.getActions();
|
|
223
|
+
expect(storeActions.length).toEqual(expectedActions.length);
|
|
224
|
+
expectedActions.map((action, index) => Object.keys(action).map(key => expect(storeActions[index][key]).toEqual(action[key])));
|
|
225
|
+
});
|
|
226
|
+
it('should try to derive the onboarding state based on the stored state of the environment', async () => {
|
|
227
|
+
const store = mockStore({ ...defaultState });
|
|
228
|
+
const stepNames = Object.keys(onboardingSteps);
|
|
229
|
+
await store.dispatch(getOnboardingState(stepNames[0]));
|
|
230
|
+
const expectedActions = expectedOnboardingActions;
|
|
231
|
+
const storeActions = store.getActions();
|
|
232
|
+
expect(storeActions.length).toEqual(expectedActions.length);
|
|
233
|
+
expectedActions.map((action, index) => Object.keys(action).map(key => expect(storeActions[index][key]).toEqual(action[key])));
|
|
234
|
+
});
|
|
235
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Copyright 2020 Northern.tech AS
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// @ts-nocheck
|
|
15
|
+
import { DEVICE_STATES, onboardingSteps as onboardingStepNames, orderedOnboardingSteps as onboardingSteps } from '@northern.tech/store/constants';
|
|
16
|
+
import { getOnboardingState as getCurrentOnboardingState, getUserCapabilities } from '@northern.tech/store/selectors';
|
|
17
|
+
import { saveUserSettings } from '@northern.tech/store/thunks';
|
|
18
|
+
import { getDemoDeviceAddress } from '@northern.tech/utils/helpers';
|
|
19
|
+
import { createAsyncThunk } from '@reduxjs/toolkit';
|
|
20
|
+
import Cookies from 'universal-cookie';
|
|
21
|
+
|
|
22
|
+
import { actions, sliceName } from '.';
|
|
23
|
+
|
|
24
|
+
const cookies = new Cookies();
|
|
25
|
+
|
|
26
|
+
export const applyOnboardingFallbacks = progress => {
|
|
27
|
+
const step = onboardingSteps[progress];
|
|
28
|
+
if (step && step.fallbackStep) {
|
|
29
|
+
return step.fallbackStep;
|
|
30
|
+
}
|
|
31
|
+
return progress;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const determineProgress = (acceptedDevices, pendingDevices, releases, pastDeployments) => {
|
|
35
|
+
const steps = onboardingSteps;
|
|
36
|
+
let progress = -1;
|
|
37
|
+
progress = pendingDevices.length > 1 ? steps.findIndex(step => step === onboardingStepNames.DEVICES_PENDING_ACCEPTING_ONBOARDING) : progress;
|
|
38
|
+
progress = acceptedDevices.length >= 1 ? steps.findIndex(step => step === onboardingStepNames.DEVICES_ACCEPTED_ONBOARDING) : progress;
|
|
39
|
+
progress =
|
|
40
|
+
acceptedDevices.length > 1 && releases.length > 1 && pastDeployments.length > 1
|
|
41
|
+
? steps.findIndex(step => step === onboardingStepNames.DEPLOYMENTS_PAST_COMPLETED)
|
|
42
|
+
: progress;
|
|
43
|
+
return steps[progress];
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const deductOnboardingState = ({ devicesById, devicesByStatus, onboardingState, pastDeployments, releases, userCapabilities, userId }) => {
|
|
47
|
+
const { canDeploy, canManageDevices, canReadDeployments, canReadDevices, canReadReleases, canUploadReleases } = userCapabilities;
|
|
48
|
+
const userCookie = cookies.get(`${userId}-onboarded`);
|
|
49
|
+
const acceptedDevices = devicesByStatus[DEVICE_STATES.accepted].deviceIds;
|
|
50
|
+
const pendingDevices = devicesByStatus[DEVICE_STATES.pending].deviceIds;
|
|
51
|
+
let deviceType = onboardingState.deviceType ?? [];
|
|
52
|
+
deviceType =
|
|
53
|
+
!deviceType.length && acceptedDevices.length && devicesById[acceptedDevices[0]].hasOwnProperty('attributes')
|
|
54
|
+
? devicesById[acceptedDevices[0]].attributes.device_type
|
|
55
|
+
: deviceType;
|
|
56
|
+
const progress = applyOnboardingFallbacks(onboardingState.progress || determineProgress(acceptedDevices, pendingDevices, releases, pastDeployments));
|
|
57
|
+
return {
|
|
58
|
+
...onboardingState,
|
|
59
|
+
complete: !!(
|
|
60
|
+
Boolean(userCookie) ||
|
|
61
|
+
onboardingState.complete ||
|
|
62
|
+
(acceptedDevices.length > 1 && pendingDevices.length > 0 && releases.length > 1 && pastDeployments.length > 1) ||
|
|
63
|
+
(acceptedDevices.length >= 1 && releases.length >= 2 && pastDeployments.length > 2) ||
|
|
64
|
+
(acceptedDevices.length >= 1 && pendingDevices.length > 0 && releases.length >= 2 && pastDeployments.length >= 2) ||
|
|
65
|
+
onboardingSteps.findIndex(step => step === progress) >= onboardingSteps.length - 1 ||
|
|
66
|
+
onboardingState.disable ||
|
|
67
|
+
![canDeploy, canManageDevices, canReadDeployments, canReadDevices, canReadReleases, canUploadReleases].every(i => i)
|
|
68
|
+
),
|
|
69
|
+
showTips: onboardingState.showTips != null ? onboardingState.showTips : true,
|
|
70
|
+
deviceType,
|
|
71
|
+
approach: onboardingState.approach || (deviceType.some(type => type.startsWith('qemu')) ? 'virtual' : 'physical'),
|
|
72
|
+
progress
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const getOnboardingState = createAsyncThunk(`${sliceName}/getOnboardingState`, (_, { dispatch, getState }) => {
|
|
77
|
+
const state = getState();
|
|
78
|
+
let onboardingState = getCurrentOnboardingState(state);
|
|
79
|
+
if (!onboardingState.complete) {
|
|
80
|
+
const userId = state.users.currentUser;
|
|
81
|
+
onboardingState = deductOnboardingState({
|
|
82
|
+
devicesById: state.devices.byId,
|
|
83
|
+
devicesByStatus: state.devices.byStatus,
|
|
84
|
+
onboardingState,
|
|
85
|
+
pastDeployments: state.deployments.byStatus.finished.deploymentIds,
|
|
86
|
+
releases: Object.values(state.releases.byId),
|
|
87
|
+
userCapabilities: getUserCapabilities(state),
|
|
88
|
+
userId
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
onboardingState.progress = onboardingState.progress || onboardingStepNames.DASHBOARD_ONBOARDING_START;
|
|
92
|
+
const demoDeviceAddress = `http://${getDemoDeviceAddress(Object.values(state.devices.byId), onboardingState.approach)}`;
|
|
93
|
+
onboardingState.address = state.onboarding.demoArtifactPort ? `${demoDeviceAddress}:${state.onboarding.demoArtifactPort}` : demoDeviceAddress;
|
|
94
|
+
return Promise.all([
|
|
95
|
+
dispatch(actions.setOnboardingComplete(onboardingState.complete)),
|
|
96
|
+
dispatch(actions.setOnboardingState(onboardingState)),
|
|
97
|
+
dispatch(saveUserSettings({ onboarding: onboardingState }))
|
|
98
|
+
]);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export const setOnboardingDeviceType = createAsyncThunk(`${sliceName}/setOnboardingDeviceType`, (value, { dispatch }) =>
|
|
102
|
+
Promise.all([dispatch(actions.setOnboardingDeviceType(value)), dispatch(saveUserSettings({ onboarding: { deviceType: value } }))])
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
export const setOnboardingApproach = createAsyncThunk(`${sliceName}/setOnboardingApproach`, (value, { dispatch }) =>
|
|
106
|
+
Promise.all([dispatch(actions.setOnboardingApproach(value)), dispatch(saveUserSettings({ onboarding: { approach: value } }))])
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
export const setOnboardingComplete = createAsyncThunk(`${sliceName}/setOnboardingComplete`, (value, { dispatch }) => {
|
|
110
|
+
let tasks = [Promise.resolve(dispatch(actions.setOnboardingComplete(value)))];
|
|
111
|
+
if (value) {
|
|
112
|
+
tasks.push(Promise.resolve(dispatch(actions.setShowOnboardingHelp(false))));
|
|
113
|
+
tasks.push(Promise.resolve(dispatch(advanceOnboarding(onboardingStepNames.DEPLOYMENTS_PAST_COMPLETED))));
|
|
114
|
+
}
|
|
115
|
+
return Promise.all(tasks);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export const setOnboardingCanceled = createAsyncThunk(`${sliceName}/setOnboardingCanceled`, (_, { dispatch }) =>
|
|
119
|
+
Promise.all([
|
|
120
|
+
Promise.resolve(dispatch(actions.setShowOnboardingHelp(false))),
|
|
121
|
+
Promise.resolve(dispatch(actions.setShowDismissOnboardingTipsDialog(false))),
|
|
122
|
+
Promise.resolve(dispatch(actions.setOnboardingComplete(true)))
|
|
123
|
+
])
|
|
124
|
+
// using DEPLOYMENTS_PAST_COMPLETED to ensure we get the intended onboarding state set after
|
|
125
|
+
// _advancing_ the onboarding progress
|
|
126
|
+
.then(() => dispatch(advanceOnboarding(onboardingStepNames.DEPLOYMENTS_PAST_COMPLETED_FAILURE)))
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
export const advanceOnboarding = createAsyncThunk(`${sliceName}/advanceOnboarding`, (stepId, { dispatch, getState }) => {
|
|
130
|
+
const steps = onboardingSteps;
|
|
131
|
+
const progress = steps.findIndex(step => step === getState().onboarding.progress);
|
|
132
|
+
const stepIndex = steps.findIndex(step => step === stepId);
|
|
133
|
+
// if there is no progress set yet, the onboarding state deduction hasn't happened
|
|
134
|
+
// and the subsequent settings persistence would overwrite what we stored
|
|
135
|
+
if (progress > stepIndex || getState().onboarding.progress === null) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const madeProgress = steps[stepIndex + 1];
|
|
139
|
+
const state = { ...getCurrentOnboardingState(getState()), progress: madeProgress };
|
|
140
|
+
state.complete = stepIndex + 1 >= steps.findIndex(step => step === onboardingStepNames.DEPLOYMENTS_PAST_COMPLETED_FAILURE) ? true : state.complete;
|
|
141
|
+
return Promise.all([dispatch(actions.setOnboardingProgress(madeProgress)), dispatch(saveUserSettings({ onboarding: state }))]);
|
|
142
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright 2020 Northern.tech AS
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// @ts-nocheck
|
|
15
|
+
import { Integration } from '@northern.tech/store/api/types/MenderTypes';
|
|
16
|
+
import { EXTERNAL_PROVIDER, apiUrl, useradmApiUrl } from '@northern.tech/store/constants';
|
|
17
|
+
|
|
18
|
+
export const auditLogsApiUrl = `${apiUrl.v1}/auditlogs`;
|
|
19
|
+
export const tenantadmApiUrlv1 = `${apiUrl.v1}/tenantadm`;
|
|
20
|
+
export const tenantadmApiUrlv2 = `${apiUrl.v2}/tenantadm`;
|
|
21
|
+
export const ssoIdpApiUrlv1 = `${apiUrl.v1}/useradm/sso/idp/metadata`;
|
|
22
|
+
|
|
23
|
+
export const XML_METADATA_FORMAT = 'xml';
|
|
24
|
+
export const JSON_METADATA_FORMAT = 'json';
|
|
25
|
+
|
|
26
|
+
export const getSamlStartUrl = id => `${window.location.origin}${useradmApiUrl}/auth/sso/${id}/login`;
|
|
27
|
+
export const getOidcStartUrl = id => `${window.location.origin}${useradmApiUrl}/oidc/${id}/start`;
|
|
28
|
+
|
|
29
|
+
export const SSO_TYPES = {
|
|
30
|
+
saml: {
|
|
31
|
+
id: 'saml',
|
|
32
|
+
type: 'saml',
|
|
33
|
+
title: 'SAML',
|
|
34
|
+
metadataFormat: XML_METADATA_FORMAT,
|
|
35
|
+
editorLanguage: XML_METADATA_FORMAT,
|
|
36
|
+
contentType: 'application/samlmetadata+xml',
|
|
37
|
+
getStartUrl: getSamlStartUrl,
|
|
38
|
+
configDetails: [
|
|
39
|
+
{ key: 'entityID', label: 'Entity ID', getValue: id => `${window.location.origin}${useradmApiUrl}/sso/sp/metadata/${id}` },
|
|
40
|
+
{ key: 'acs', label: 'ACS URL', getValue: id => `${window.location.origin}${useradmApiUrl}/auth/sso/${id}/acs` },
|
|
41
|
+
{ key: 'startURL', label: 'Start URL', getValue: getSamlStartUrl }
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
oidc: {
|
|
45
|
+
id: 'oidc',
|
|
46
|
+
type: 'oidc',
|
|
47
|
+
title: 'OpenID Connect',
|
|
48
|
+
metadataFormat: JSON_METADATA_FORMAT,
|
|
49
|
+
editorLanguage: JSON_METADATA_FORMAT,
|
|
50
|
+
contentType: 'application/json',
|
|
51
|
+
getStartUrl: getOidcStartUrl,
|
|
52
|
+
configDetails: [{ key: 'startURL', label: 'Start Url', getValue: getOidcStartUrl }]
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const AUDIT_LOGS_TYPES = [
|
|
57
|
+
{ title: 'Artifact', queryParameter: 'object_type', value: 'artifact' },
|
|
58
|
+
{ title: 'Deployment', queryParameter: 'object_deployment_name', value: 'deployment' },
|
|
59
|
+
{ title: 'Device', queryParameter: 'object_id', value: 'device' },
|
|
60
|
+
{ title: 'User', queryParameter: 'object_id', value: 'user' }
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
export interface Webhook extends Integration {
|
|
64
|
+
provider: Integration.provider.WEBHOOK;
|
|
65
|
+
scopes?: string[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const emptyWebhook: Webhook = {
|
|
69
|
+
description: '',
|
|
70
|
+
enabled: true,
|
|
71
|
+
credentials: {
|
|
72
|
+
type: EXTERNAL_PROVIDER.webhook.credentialsType,
|
|
73
|
+
[EXTERNAL_PROVIDER.webhook.credentialsType]: {
|
|
74
|
+
secret: '',
|
|
75
|
+
url: ''
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
export const TENANT_LIST_DEFAULT = {
|
|
80
|
+
page: 1,
|
|
81
|
+
perPage: 20
|
|
82
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Copyright 2023 Northern.tech AS
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import { DEVICE_LIST_DEFAULTS, SORTING_OPTIONS, TENANT_LIST_DEFAULT } from '@northern.tech/store/constants';
|
|
15
|
+
import { createSlice } from '@reduxjs/toolkit';
|
|
16
|
+
|
|
17
|
+
export const sliceName = 'organization';
|
|
18
|
+
|
|
19
|
+
export const initialState = {
|
|
20
|
+
card: {
|
|
21
|
+
last4: '',
|
|
22
|
+
expiration: { month: 1, year: 2020 },
|
|
23
|
+
brand: ''
|
|
24
|
+
},
|
|
25
|
+
intentId: null,
|
|
26
|
+
organization: {
|
|
27
|
+
tenantList: {
|
|
28
|
+
...TENANT_LIST_DEFAULT,
|
|
29
|
+
total: 0,
|
|
30
|
+
tenants: [],
|
|
31
|
+
selectedTenant: null,
|
|
32
|
+
sort: {
|
|
33
|
+
direction: SORTING_OPTIONS.desc,
|
|
34
|
+
key: 'name'
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// id, name, status, tenant_token, plan
|
|
38
|
+
},
|
|
39
|
+
auditlog: {
|
|
40
|
+
events: [],
|
|
41
|
+
selectionState: {
|
|
42
|
+
...DEVICE_LIST_DEFAULTS,
|
|
43
|
+
detail: undefined,
|
|
44
|
+
endDate: undefined,
|
|
45
|
+
selectedIssue: undefined,
|
|
46
|
+
sort: { direction: SORTING_OPTIONS.desc },
|
|
47
|
+
startDate: undefined,
|
|
48
|
+
total: 0,
|
|
49
|
+
type: undefined,
|
|
50
|
+
user: undefined
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
externalDeviceIntegrations: [
|
|
54
|
+
// { <connection_string|x509|...>, id, provider }
|
|
55
|
+
],
|
|
56
|
+
ssoConfigs: [],
|
|
57
|
+
webhooks: {
|
|
58
|
+
// [id]: { events: [] }
|
|
59
|
+
// for now:
|
|
60
|
+
events: [],
|
|
61
|
+
eventsTotal: 0
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const organizationSlice = createSlice({
|
|
66
|
+
name: sliceName,
|
|
67
|
+
initialState,
|
|
68
|
+
reducers: {
|
|
69
|
+
receiveAuditLogs: (state, action) => {
|
|
70
|
+
const { events, total } = action.payload;
|
|
71
|
+
state.auditlog.events = events;
|
|
72
|
+
state.auditlog.selectionState.total = total;
|
|
73
|
+
},
|
|
74
|
+
setAuditLogState: (state, action) => {
|
|
75
|
+
state.auditlog.selectionState = {
|
|
76
|
+
...state.auditlog.selectionState,
|
|
77
|
+
...action.payload
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
receiveCurrentCard: (state, action) => {
|
|
81
|
+
state.card = action.payload;
|
|
82
|
+
},
|
|
83
|
+
receiveSetupIntent: (state, action) => {
|
|
84
|
+
state.intentId = action.payload;
|
|
85
|
+
},
|
|
86
|
+
setOrganization: (state, action) => {
|
|
87
|
+
state.organization = {
|
|
88
|
+
...state.organization,
|
|
89
|
+
...action.payload,
|
|
90
|
+
tenantList: { ...state.organization.tenantList, ...action.payload.tenantList }
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
setTenantListState: (state, action) => {
|
|
94
|
+
state.organization.tenantList = action.payload;
|
|
95
|
+
},
|
|
96
|
+
receiveExternalDeviceIntegrations: (state, action) => {
|
|
97
|
+
state.externalDeviceIntegrations = action.payload;
|
|
98
|
+
},
|
|
99
|
+
receiveSsoConfigs: (state, action) => {
|
|
100
|
+
state.ssoConfigs = action.payload;
|
|
101
|
+
},
|
|
102
|
+
receiveWebhookEvents: (state, action) => {
|
|
103
|
+
const { value, total } = action.payload;
|
|
104
|
+
state.webhooks.events = value;
|
|
105
|
+
state.webhooks.eventsTotal = total;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export const actions = organizationSlice.actions;
|
|
111
|
+
export default organizationSlice.reducer;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Copyright 2020 Northern.tech AS
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// @ts-nocheck
|
|
15
|
+
import { SORTING_OPTIONS } from '@northern.tech/store/commonConstants';
|
|
16
|
+
|
|
17
|
+
import reducer, { actions, initialState } from '.';
|
|
18
|
+
import { defaultState } from '../../../../tests/mockData';
|
|
19
|
+
|
|
20
|
+
describe('organization reducer', () => {
|
|
21
|
+
it('should return the initial state', async () => {
|
|
22
|
+
expect(reducer(undefined, {})).toEqual(initialState);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should handle RECEIVE_AUDIT_LOGS', async () => {
|
|
26
|
+
expect(
|
|
27
|
+
reducer(undefined, { type: actions.receiveAuditLogs, payload: { events: defaultState.organization.auditlog.events, total: 2 } }).auditlog.selectionState
|
|
28
|
+
.total
|
|
29
|
+
).toEqual(2);
|
|
30
|
+
expect(
|
|
31
|
+
reducer(initialState, { type: actions.receiveAuditLogs, payload: { events: defaultState.organization.auditlog.events, total: 4 } }).auditlog
|
|
32
|
+
.selectionState.total
|
|
33
|
+
).toEqual(4);
|
|
34
|
+
});
|
|
35
|
+
it('should handle SET_AUDITLOG_STATE', async () => {
|
|
36
|
+
const newState = { something: 'new' };
|
|
37
|
+
expect(reducer(undefined, { type: actions.setAuditLogState, payload: newState }).auditlog.selectionState.something).toEqual(newState.something);
|
|
38
|
+
expect(reducer(initialState, { type: actions.setAuditLogState, payload: newState }).auditlog.selectionState).toEqual({
|
|
39
|
+
...defaultState.organization.auditlog.selectionState,
|
|
40
|
+
...newState,
|
|
41
|
+
sort: { direction: SORTING_OPTIONS.desc },
|
|
42
|
+
total: 0
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
it('should handle RECEIVE_CURRENT_CARD', async () => {
|
|
46
|
+
expect(reducer(undefined, { type: actions.receiveCurrentCard, payload: defaultState.organization.card }).card).toEqual(defaultState.organization.card);
|
|
47
|
+
expect(reducer(initialState, { type: actions.receiveCurrentCard, payload: defaultState.organization.card }).card).toEqual(defaultState.organization.card);
|
|
48
|
+
});
|
|
49
|
+
it('should handle RECEIVE_SETUP_INTENT', async () => {
|
|
50
|
+
expect(reducer(undefined, { type: actions.receiveSetupIntent, payload: defaultState.organization.intentId }).intentId).toEqual(
|
|
51
|
+
defaultState.organization.intentId
|
|
52
|
+
);
|
|
53
|
+
expect(reducer(initialState, { type: actions.receiveSetupIntent, payload: 4 }).intentId).toEqual(4);
|
|
54
|
+
});
|
|
55
|
+
it('should handle SET_ORGANIZATION', async () => {
|
|
56
|
+
expect(reducer(undefined, { type: actions.setOrganization, payload: defaultState.organization.organization }).organization.plan).toEqual(
|
|
57
|
+
defaultState.organization.organization.plan
|
|
58
|
+
);
|
|
59
|
+
expect(reducer(initialState, { type: actions.setOrganization, payload: defaultState.organization.organization }).organization.name).toEqual(
|
|
60
|
+
defaultState.organization.organization.name
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
it('should handle RECEIVE_EXTERNAL_DEVICE_INTEGRATIONS', async () => {
|
|
64
|
+
expect(reducer(undefined, { type: actions.receiveExternalDeviceIntegrations, payload: [] }).externalDeviceIntegrations).toEqual([]);
|
|
65
|
+
expect(reducer(initialState, { type: actions.receiveExternalDeviceIntegrations, payload: [12, 23] }).externalDeviceIntegrations).toEqual([12, 23]);
|
|
66
|
+
});
|
|
67
|
+
it('should handle RECEIVE_WEBHOOK_EVENTS', async () => {
|
|
68
|
+
expect(reducer(undefined, { type: actions.receiveWebhookEvents, payload: { value: [] } }).webhooks.events).toEqual([]);
|
|
69
|
+
expect(reducer(initialState, { type: actions.receiveWebhookEvents, payload: { value: [12, 23], total: 5 } }).webhooks).toEqual({
|
|
70
|
+
events: [12, 23],
|
|
71
|
+
eventsTotal: 5
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
it('should handle RECEIVE_SSO_CONFIGS', async () => {
|
|
75
|
+
expect(reducer(undefined, { type: actions.receiveSsoConfigs, payload: [] }).ssoConfigs).toEqual([]);
|
|
76
|
+
expect(reducer(initialState, { type: actions.receiveSsoConfigs, payload: [12, 23] }).ssoConfigs).toEqual([12, 23]);
|
|
77
|
+
});
|
|
78
|
+
});
|