feat(user-config): Upload user configuration from json/bin file (#545)
* feat(user-config): Upload user configuration from json/bin file * fix error message * remove file extension filter * apply user config after loaded from file * add file filter * remove file filter
This commit is contained in:
committed by
László Monda
parent
b3f2e3451e
commit
f0139c55ee
@@ -14,9 +14,11 @@
|
|||||||
<span role="button" class="btn-link" (click)="saveConfigurationInBINFormat()">binary</span> format.
|
<span role="button" class="btn-link" (click)="saveConfigurationInBINFormat()">binary</span> format.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button class="btn btn-default"
|
<label class="btn btn-default btn-file">
|
||||||
>Upload device configuration
|
Upload device configuration
|
||||||
</button>
|
<input type="file"
|
||||||
|
(change)="changeFile($event)">
|
||||||
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button class="btn btn-danger"
|
<button class="btn btn-danger"
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ import { Store } from '@ngrx/store';
|
|||||||
|
|
||||||
import { AppState } from '../../../store';
|
import { AppState } from '../../../store';
|
||||||
import { ResetUserConfigurationAction } from '../../../store/actions/device';
|
import { ResetUserConfigurationAction } from '../../../store/actions/device';
|
||||||
import { SaveUserConfigInBinaryFileAction, SaveUserConfigInJsonFileAction } from '../../../store/actions/user-config';
|
import {
|
||||||
|
LoadUserConfigurationFromFileAction,
|
||||||
|
SaveUserConfigInBinaryFileAction,
|
||||||
|
SaveUserConfigInJsonFileAction
|
||||||
|
} from '../../../store/actions/user-config';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'device-settings',
|
selector: 'device-settings',
|
||||||
@@ -29,4 +33,17 @@ export class DeviceConfigurationComponent {
|
|||||||
saveConfigurationInBINFormat() {
|
saveConfigurationInBINFormat() {
|
||||||
this.store.dispatch(new SaveUserConfigInBinaryFileAction());
|
this.store.dispatch(new SaveUserConfigInBinaryFileAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeFile(event): void {
|
||||||
|
const files = event.srcElement.files;
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onloadend = function () {
|
||||||
|
const arrayBuffer = new Uint8Array(fileReader.result);
|
||||||
|
this.store.dispatch(new LoadUserConfigurationFromFileAction({
|
||||||
|
filename: event.srcElement.value,
|
||||||
|
data: Array.from(arrayBuffer)
|
||||||
|
}));
|
||||||
|
}.bind(this);
|
||||||
|
fileReader.readAsArrayBuffer(files[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
packages/uhk-web/src/app/models/upload-file-data.ts
Normal file
4
packages/uhk-web/src/app/models/upload-file-data.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export interface UploadFileData {
|
||||||
|
filename: string;
|
||||||
|
data: Array<number>;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
import { type, UserConfiguration, ConfigurationReply } from 'uhk-common';
|
import { type, UserConfiguration, ConfigurationReply } from 'uhk-common';
|
||||||
import { UserConfigurationValue } from '../../models/user-configuration-value';
|
import { UserConfigurationValue } from '../../models/user-configuration-value';
|
||||||
|
import { UploadFileData } from '../../models/upload-file-data';
|
||||||
|
|
||||||
const PREFIX = '[user-config] ';
|
const PREFIX = '[user-config] ';
|
||||||
|
|
||||||
@@ -15,7 +16,9 @@ export const ActionTypes = {
|
|||||||
SAVE_USER_CONFIG_IN_BIN_FILE: type(PREFIX + 'Save User Config in binary file'),
|
SAVE_USER_CONFIG_IN_BIN_FILE: type(PREFIX + 'Save User Config in binary file'),
|
||||||
LOAD_RESET_USER_CONFIGURATION: type(PREFIX + 'Load reset user configuration'),
|
LOAD_RESET_USER_CONFIGURATION: type(PREFIX + 'Load reset user configuration'),
|
||||||
RENAME_USER_CONFIGURATION: type(PREFIX + 'Rename user configuration'),
|
RENAME_USER_CONFIGURATION: type(PREFIX + 'Rename user configuration'),
|
||||||
SET_USER_CONFIGURATION_VALUE: type(PREFIX + 'Set user configuration value')
|
SET_USER_CONFIGURATION_VALUE: type(PREFIX + 'Set user configuration value'),
|
||||||
|
LOAD_USER_CONFIGURATION_FROM_FILE: type(PREFIX + 'Load user configuration from file'),
|
||||||
|
APPLY_USER_CONFIGURATION_FROM_FILE: type(PREFIX + 'Apply user configuration from file')
|
||||||
};
|
};
|
||||||
|
|
||||||
export class LoadUserConfigAction implements Action {
|
export class LoadUserConfigAction implements Action {
|
||||||
@@ -76,6 +79,20 @@ export class SetUserConfigurationValueAction implements Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class LoadUserConfigurationFromFileAction implements Action {
|
||||||
|
type = ActionTypes.LOAD_USER_CONFIGURATION_FROM_FILE;
|
||||||
|
|
||||||
|
constructor(public payload: UploadFileData) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApplyUserConfigurationFromFileAction implements Action {
|
||||||
|
type = ActionTypes.APPLY_USER_CONFIGURATION_FROM_FILE;
|
||||||
|
|
||||||
|
constructor(public payload: UserConfiguration) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type Actions
|
export type Actions
|
||||||
= LoadUserConfigAction
|
= LoadUserConfigAction
|
||||||
| LoadUserConfigSuccessAction
|
| LoadUserConfigSuccessAction
|
||||||
@@ -87,4 +104,6 @@ export type Actions
|
|||||||
| LoadResetUserConfigurationAction
|
| LoadResetUserConfigurationAction
|
||||||
| RenameUserConfigurationAction
|
| RenameUserConfigurationAction
|
||||||
| SetUserConfigurationValueAction
|
| SetUserConfigurationValueAction
|
||||||
|
| LoadUserConfigurationFromFileAction
|
||||||
|
| ApplyUserConfigurationFromFileAction
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ export class DeviceEffects {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@Effect() saveResetUserConfigurationToDevice$ = this.actions$
|
@Effect() saveResetUserConfigurationToDevice$ = this.actions$
|
||||||
.ofType(UserConfigActions.LOAD_RESET_USER_CONFIGURATION)
|
.ofType(UserConfigActions.LOAD_RESET_USER_CONFIGURATION, UserConfigActions.APPLY_USER_CONFIGURATION_FROM_FILE)
|
||||||
.switchMap(() => Observable.of(new SaveConfigurationAction()));
|
.switchMap(() => Observable.of(new SaveConfigurationAction()));
|
||||||
|
|
||||||
@Effect({dispatch: false}) updateFirmware$ = this.actions$
|
@Effect({dispatch: false}) updateFirmware$ = this.actions$
|
||||||
|
|||||||
@@ -15,12 +15,21 @@ import 'rxjs/add/observable/of';
|
|||||||
import 'rxjs/add/observable/empty';
|
import 'rxjs/add/observable/empty';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ConfigurationReply, HardwareConfiguration, LogService, NotificationType, UhkBuffer,
|
ConfigurationReply,
|
||||||
|
HardwareConfiguration,
|
||||||
|
LogService,
|
||||||
|
NotificationType,
|
||||||
|
UhkBuffer,
|
||||||
UserConfiguration
|
UserConfiguration
|
||||||
} from 'uhk-common';
|
} from 'uhk-common';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActionTypes, LoadConfigFromDeviceReplyAction, LoadUserConfigSuccessAction, RenameUserConfigurationAction,
|
ActionTypes,
|
||||||
|
ApplyUserConfigurationFromFileAction,
|
||||||
|
LoadConfigFromDeviceReplyAction,
|
||||||
|
LoadUserConfigSuccessAction,
|
||||||
|
LoadUserConfigurationFromFileAction,
|
||||||
|
RenameUserConfigurationAction,
|
||||||
SaveUserConfigSuccessAction
|
SaveUserConfigSuccessAction
|
||||||
} from '../actions/user-config';
|
} from '../actions/user-config';
|
||||||
|
|
||||||
@@ -29,12 +38,15 @@ import { DefaultUserConfigurationService } from '../../services/default-user-con
|
|||||||
import { AppState, autoWriteUserConfiguration, getPrevUserConfiguration, getUserConfiguration } from '../index';
|
import { AppState, autoWriteUserConfiguration, getPrevUserConfiguration, getUserConfiguration } from '../index';
|
||||||
import { KeymapAction, KeymapActions, MacroAction, MacroActions } from '../actions';
|
import { KeymapAction, KeymapActions, MacroAction, MacroActions } from '../actions';
|
||||||
import {
|
import {
|
||||||
DismissUndoNotificationAction, LoadHardwareConfigurationSuccessAction, ShowNotificationAction,
|
DismissUndoNotificationAction,
|
||||||
|
LoadHardwareConfigurationSuccessAction,
|
||||||
|
ShowNotificationAction,
|
||||||
UndoLastAction
|
UndoLastAction
|
||||||
} from '../actions/app';
|
} from '../actions/app';
|
||||||
import { SaveConfigurationAction, ShowSaveToKeyboardButtonAction } from '../actions/device';
|
import { SaveConfigurationAction, ShowSaveToKeyboardButtonAction } from '../actions/device';
|
||||||
import { DeviceRendererService } from '../../services/device-renderer.service';
|
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||||
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
||||||
|
import { UploadFileData } from '../../models/upload-file-data';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserConfigEffects {
|
export class UserConfigEffects {
|
||||||
@@ -198,6 +210,38 @@ export class UserConfigEffects {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@Effect() loadUserConfigurationFromFile$ = this.actions$
|
||||||
|
.ofType<LoadUserConfigurationFromFileAction>(ActionTypes.LOAD_USER_CONFIGURATION_FROM_FILE)
|
||||||
|
.map(action => action.payload)
|
||||||
|
.map((info: UploadFileData) => {
|
||||||
|
try {
|
||||||
|
const userConfig = new UserConfiguration();
|
||||||
|
|
||||||
|
if (info.filename.endsWith('.bin')) {
|
||||||
|
userConfig.fromBinary(UhkBuffer.fromArray(info.data));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const buffer = new Buffer(info.data);
|
||||||
|
const json = buffer.toString();
|
||||||
|
userConfig.fromJsonObject(JSON.parse(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userConfig.userConfigMajorVersion) {
|
||||||
|
return new ApplyUserConfigurationFromFileAction(userConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ShowNotificationAction({
|
||||||
|
type: NotificationType.Error,
|
||||||
|
message: 'Invalid configuration specified.'
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
return new ShowNotificationAction({
|
||||||
|
type: NotificationType.Error,
|
||||||
|
message: 'Invalid configuration specified.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
constructor(private actions$: Actions,
|
constructor(private actions$: Actions,
|
||||||
private dataStorageRepository: DataStorageRepositoryService,
|
private dataStorageRepository: DataStorageRepositoryService,
|
||||||
private store: Store<AppState>,
|
private store: Store<AppState>,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export function reducer(state = initialState, action: Action & { payload?: any }
|
|||||||
const changedUserConfiguration: UserConfiguration = Object.assign(new UserConfiguration(), state);
|
const changedUserConfiguration: UserConfiguration = Object.assign(new UserConfiguration(), state);
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case ActionTypes.APPLY_USER_CONFIGURATION_FROM_FILE:
|
||||||
case ActionTypes.LOAD_RESET_USER_CONFIGURATION:
|
case ActionTypes.LOAD_RESET_USER_CONFIGURATION:
|
||||||
case ActionTypes.LOAD_USER_CONFIG_SUCCESS: {
|
case ActionTypes.LOAD_USER_CONFIG_SUCCESS: {
|
||||||
return Object.assign(changedUserConfiguration, action.payload);
|
return Object.assign(changedUserConfiguration, action.payload);
|
||||||
|
|||||||
@@ -94,3 +94,24 @@ a.disabled {
|
|||||||
.noUi-value {
|
.noUi-value {
|
||||||
top: 2rem;
|
top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-file {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
input[type=file] {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
font-size: 100px;
|
||||||
|
text-align: right;
|
||||||
|
filter: alpha(opacity=0);
|
||||||
|
opacity: 0;
|
||||||
|
outline: none;
|
||||||
|
background: white;
|
||||||
|
cursor: inherit;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user