mirror of
https://github.com/Telecominfraproject/wlan-sdk-mobile-app.git
synced 2025-11-01 19:27:56 +00:00
General cleanup and refinement of the DeviceDetails screen. Implemented more expected functionality, streamlines some patterns. Also fixed some minor issues with the wrong strings due to cut and paste errors.
This commit is contained in:
10
src/Utils.js
10
src/Utils.js
@@ -13,6 +13,16 @@ export function showGeneralMessage(message) {
|
|||||||
Alert.alert(strings.messages.titleMessage, message);
|
Alert.alert(strings.messages.titleMessage, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function displayValue(obj, key) {
|
||||||
|
if (obj && key) {
|
||||||
|
if (key in obj) {
|
||||||
|
return obj[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.messages.empty;
|
||||||
|
}
|
||||||
|
|
||||||
export function logStringifyPretty(obj, title) {
|
export function logStringifyPretty(obj, title) {
|
||||||
if (title) {
|
if (title) {
|
||||||
console.log(title, JSON.stringify(obj, null, '\t'));
|
console.log(title, JSON.stringify(obj, null, '\t'));
|
||||||
|
|||||||
BIN
src/assets/network-wired-solid.png
Normal file
BIN
src/assets/network-wired-solid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 956 B |
@@ -20,15 +20,16 @@ export const strings = new LocalizedStrings({
|
|||||||
missingEndpoints: 'System is not set up correct - missing configuration information.',
|
missingEndpoints: 'System is not set up correct - missing configuration information.',
|
||||||
samePassword: 'Password is the same as old password.',
|
samePassword: 'Password is the same as old password.',
|
||||||
titleDashboard: 'Dashboard',
|
titleDashboard: 'Dashboard',
|
||||||
titleSignIn: 'Sign In Error',
|
titleDeviceDetails: 'Device Error',
|
||||||
titleSystemSetup: 'System Setup Error',
|
|
||||||
titleDeviceList: 'Devices Error',
|
titleDeviceList: 'Devices Error',
|
||||||
titleForgotPassword: 'Forgot Password Error',
|
titleForgotPassword: 'Forgot Password Error',
|
||||||
|
titleMfa: 'Multi-Factor Authentication Error',
|
||||||
titleNetwork: 'Network Error',
|
titleNetwork: 'Network Error',
|
||||||
titleProfile: 'Profile Error',
|
titleProfile: 'Profile Error',
|
||||||
titleResetPassword: 'Reset Password Error',
|
titleResetPassword: 'Reset Password Error',
|
||||||
|
titleSignIn: 'Sign In Error',
|
||||||
titleSms: 'SMS Error',
|
titleSms: 'SMS Error',
|
||||||
titleMfa: 'Multi-Factor Authentication Error',
|
titleSystemSetup: 'System Setup Error',
|
||||||
titleUpdate: 'Update Error',
|
titleUpdate: 'Update Error',
|
||||||
token: 'Credentials no longer valid, please sign-in again.',
|
token: 'Credentials no longer valid, please sign-in again.',
|
||||||
unknown: 'Unknown error.',
|
unknown: 'Unknown error.',
|
||||||
@@ -85,6 +86,7 @@ export const strings = new LocalizedStrings({
|
|||||||
submit: 'Submit',
|
submit: 'Submit',
|
||||||
termsConditions: 'Terms & Conditions',
|
termsConditions: 'Terms & Conditions',
|
||||||
update: 'Update',
|
update: 'Update',
|
||||||
|
unpause: 'Unpause',
|
||||||
validate: 'Validate',
|
validate: 'Validate',
|
||||||
verify: 'Verify',
|
verify: 'Verify',
|
||||||
},
|
},
|
||||||
@@ -134,8 +136,11 @@ export const strings = new LocalizedStrings({
|
|||||||
wiredClients: 'Wired Clients',
|
wiredClients: 'Wired Clients',
|
||||||
},
|
},
|
||||||
deviceDetails: {
|
deviceDetails: {
|
||||||
|
connected: 'Connected',
|
||||||
connectionDetails: 'Connection Details',
|
connectionDetails: 'Connection Details',
|
||||||
connectionType: 'Connection Type',
|
connectionType: 'Connection Type',
|
||||||
|
connectionTypeWifi: 'WiFi ({0})',
|
||||||
|
connectionTypeWired: 'Wired ({0})',
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
deviceDetails: 'Device Details',
|
deviceDetails: 'Device Details',
|
||||||
ipAddress: 'IP Address',
|
ipAddress: 'IP Address',
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import { StyleSheet, SafeAreaView, ScrollView, View, Text } from 'react-native';
|
import { StyleSheet, SafeAreaView, ScrollView, View, Text } from 'react-native';
|
||||||
import { subscriberDevicesApi, handleApiError } from '../api/apiHandler';
|
import { subscriberDevicesApi, handleApiError } from '../api/apiHandler';
|
||||||
import { useFocusEffect } from '@react-navigation/native';
|
import { useFocusEffect } from '@react-navigation/native';
|
||||||
import { showGeneralError } from '../Utils';
|
import { showGeneralError, displayValue } from '../Utils';
|
||||||
import AccordionSection from '../components/AccordionSection';
|
import AccordionSection from '../components/AccordionSection';
|
||||||
import ButtonStyled from '../components/ButtonStyled';
|
import ButtonStyled from '../components/ButtonStyled';
|
||||||
import ImageWithBadge from '../components/ImageWithBadge';
|
import ImageWithBadge from '../components/ImageWithBadge';
|
||||||
@@ -44,12 +44,13 @@ const DeviceDetails = props => {
|
|||||||
|
|
||||||
const getSubsciberDevice = async (accessPointToQuery, clientToQuery) => {
|
const getSubsciberDevice = async (accessPointToQuery, clientToQuery) => {
|
||||||
if (!subscriberDevicesApi) {
|
if (!subscriberDevicesApi) {
|
||||||
|
// This is expected to be temporary
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!accessPointToQuery || !clientToQuery) {
|
if (!accessPointToQuery || !clientToQuery) {
|
||||||
showGeneralError(strings.errors.titleNetwork, strings.errors.internal);
|
showGeneralError(strings.errors.titleDeviceDetails, strings.errors.internal);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,24 +62,22 @@ const DeviceDetails = props => {
|
|||||||
|
|
||||||
const response = await subscriberDevicesApi.getSubscriberDevices(accessPointToQuery.id);
|
const response = await subscriberDevicesApi.getSubscriberDevices(accessPointToQuery.id);
|
||||||
console.log(response.data);
|
console.log(response.data);
|
||||||
if (response && response.data) {
|
|
||||||
const searchResult = response.data.devices.find(
|
|
||||||
deviceTemp => deviceTemp.macAddress === clientToQuery.macAddress,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (searchResult) {
|
if (!response || !response.data || !response.data.devices) {
|
||||||
setDevice(searchResult);
|
|
||||||
} else {
|
|
||||||
// List changed, so clear the current access point
|
|
||||||
setDevice(null);
|
|
||||||
showGeneralError(strings.errors.titleNetwork, strings.errors.noSubscriberDevice);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error('Invalid response from getSubsciberDevice');
|
console.error('Invalid response from getSubsciberDevice');
|
||||||
showGeneralError(strings.errors.titleNetwork, strings.errors.invalidResponse);
|
showGeneralError(strings.errors.titleDeviceDetails, strings.errors.invalidResponse);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const foundDevice = response.data.devices.find(deviceTemp => deviceTemp.macAddress === clientToQuery.macAddress);
|
||||||
|
if (foundDevice) {
|
||||||
|
setDevice(foundDevice);
|
||||||
|
} else {
|
||||||
|
setDevice(null);
|
||||||
|
showGeneralError(strings.errors.titleDeviceDetails, strings.errors.noSubscriberDevice);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleApiError(strings.errors.titleNetwork, error);
|
handleApiError(strings.errors.titleDeviceDetails, error);
|
||||||
} finally {
|
} finally {
|
||||||
setDeviceLoading(false);
|
setDeviceLoading(false);
|
||||||
}
|
}
|
||||||
@@ -86,7 +85,7 @@ const DeviceDetails = props => {
|
|||||||
|
|
||||||
const updateDeviceValue = jsonObject => {
|
const updateDeviceValue = jsonObject => {
|
||||||
if (jsonObject) {
|
if (jsonObject) {
|
||||||
// We are looping, but really only expect one
|
// Loop though all key/values, but really only expect one pair in the current flow
|
||||||
for (const [key, value] of Object.entries(jsonObject)) {
|
for (const [key, value] of Object.entries(jsonObject)) {
|
||||||
updateSubsciberDevice(accessPoint, client, key, value);
|
updateSubsciberDevice(accessPoint, client, key, value);
|
||||||
}
|
}
|
||||||
@@ -95,81 +94,113 @@ const DeviceDetails = props => {
|
|||||||
|
|
||||||
const updateSubsciberDevice = async (accessPointToUpdate, clientToUpdate, keyToUpdate, valueToUpdate) => {
|
const updateSubsciberDevice = async (accessPointToUpdate, clientToUpdate, keyToUpdate, valueToUpdate) => {
|
||||||
if (!subscriberDevicesApi) {
|
if (!subscriberDevicesApi) {
|
||||||
|
// This is expected to be temporary
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!accessPointToUpdate || !clientToUpdate || !keyToUpdate || !valueToUpdate) {
|
if (!accessPointToUpdate || !clientToUpdate || !keyToUpdate || !valueToUpdate) {
|
||||||
showGeneralError(strings.errors.titleNetwork, strings.errors.internal);
|
showGeneralError(strings.errors.titleDeviceDetails, strings.errors.internal);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the most current subscriber devices, we want to be as current as possible to ensure we have the latest
|
// Get the most current subscriber devices, we want to be as current as possible to ensure we have the latest
|
||||||
// values before updating the new information
|
// values before updating the new information
|
||||||
const responseGet = await subscriberDevicesApi.getSubscriberDevices(accessPointToUpdate.id);
|
const responseGet = await subscriberDevicesApi.getSubscriberDevices(accessPointToUpdate.id);
|
||||||
if (responseGet && responseGet.data) {
|
if (!responseGet || !responseGet.data || !responseGet.data.devices) {
|
||||||
let subscriberDevices = responseGet.data.devices;
|
console.error('Invalid response from getSubsciberDevice');
|
||||||
let deviceToUpdate = subscriberDevices.find(deviceTemp => deviceTemp.macAddress === clientToUpdate.macAddress);
|
showGeneralError(strings.errors.titleDeviceDetails, strings.errors.invalidResponse);
|
||||||
|
return;
|
||||||
// Update the value
|
|
||||||
deviceToUpdate[keyToUpdate] = valueToUpdate;
|
|
||||||
|
|
||||||
const responseModify = await subscriberDevicesApi.get.modifySubscriberDevices(
|
|
||||||
accessPointToUpdate.id,
|
|
||||||
false,
|
|
||||||
subscriberDevices,
|
|
||||||
);
|
|
||||||
console.log(responseModify.data);
|
|
||||||
if (responseModify && responseModify.data) {
|
|
||||||
// Updated - no need to do anyting
|
|
||||||
} else {
|
|
||||||
console.error('Invalid response from modifySubscriberDevices');
|
|
||||||
showGeneralError(strings.errors.titleNetwork, strings.errors.invalidResponse);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error('Invalid response from getSubscriberDevices');
|
|
||||||
showGeneralError(strings.errors.titleNetwork, strings.errors.invalidResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let subscriberDevices = responseGet.data.devices;
|
||||||
|
let deviceToUpdate = subscriberDevices.find(deviceTemp => deviceTemp.macAddress === clientToUpdate.macAddress);
|
||||||
|
|
||||||
|
// Update the value for the key (which will update the list as well)
|
||||||
|
deviceToUpdate[keyToUpdate] = valueToUpdate;
|
||||||
|
|
||||||
|
const responseModify = await subscriberDevicesApi.get.modifySubscriberDevices(
|
||||||
|
accessPointToUpdate.id,
|
||||||
|
false,
|
||||||
|
subscriberDevices,
|
||||||
|
);
|
||||||
|
console.log(responseModify.data);
|
||||||
|
|
||||||
|
if (!responseModify || !responseModify.data) {
|
||||||
|
console.error('Invalid response from modifySubscriberDevices');
|
||||||
|
showGeneralError(strings.errors.titleDeviceDetails, strings.errors.invalidResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Verify the response code once API has been implemented
|
||||||
|
// Do nothing if everything work as expected
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleApiError(strings.errors.titleNetwork, error);
|
handleApiError(strings.errors.titleDeviceDetails, error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getClientIcon = () => {
|
const getDeviceIcon = () => {
|
||||||
|
// TODO: Handle proper icon based on device type
|
||||||
return require('../assets/laptop-solid.png');
|
return require('../assets/laptop-solid.png');
|
||||||
};
|
};
|
||||||
|
|
||||||
const getClientBadgeIcon = () => {
|
const getDeviceBadgeIcon = () => {
|
||||||
return require('../assets/wifi-solid.png');
|
if ('ssid' in client) {
|
||||||
|
return require('../assets/wifi-solid.png');
|
||||||
|
} else {
|
||||||
|
return require('../assets/network-wired-solid.png');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getClientStatusColor = () => {
|
const getDeviceBadgeStatusColor = () => {
|
||||||
// Random choice for the moment, until the actual device parsing is implemented
|
if ('ssid' in client) {
|
||||||
let choice = Math.floor(Math.random() * 10) % 3;
|
const rssi = client.rssi;
|
||||||
|
|
||||||
switch (choice) {
|
// Handle WIFI status
|
||||||
case 2:
|
// TODO: Verify this
|
||||||
|
if (rssi <= -80) {
|
||||||
return errorColor;
|
return errorColor;
|
||||||
|
} else if (rssi > -80 && rssi <= -50) {
|
||||||
case 1:
|
|
||||||
return warnColor;
|
return warnColor;
|
||||||
|
} else if (rssi > -50 && rssi < 0) {
|
||||||
default:
|
|
||||||
case 0:
|
|
||||||
return okColor;
|
return okColor;
|
||||||
|
} else {
|
||||||
|
return errorColor;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Wired client
|
||||||
|
// TODO: Check to see if there is more to look at here
|
||||||
|
return okColor;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getClientName = () => {
|
const getClientName = () => {
|
||||||
return client ? client.name : strings.messages.empty;
|
displayValue(client, 'name');
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPausePress = async () => {
|
const onPauseUnpauseButtonLabel = () => {
|
||||||
// Handle pause
|
if (device && !device.suspended) {
|
||||||
|
return strings.buttons.unpause;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.buttons.pause;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPauseUnpausePress = async () => {
|
||||||
|
if (device) {
|
||||||
|
// Swap the current suspend state
|
||||||
|
updateDeviceValue({ suspended: !device.suspended });
|
||||||
|
} else {
|
||||||
|
showGeneralError(strings.errors.titleDeviceDetails, strings.errors.invalidResponse);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getConnectionType = () => {
|
const getConnectionType = () => {
|
||||||
return device ? device.name : strings.messages.empty;
|
// TODO: get proper connection type
|
||||||
|
if ('ssid' in client) {
|
||||||
|
return strings.formatString(strings.deviceDetails.connectionTypeWifi, displayValue(client, 'ssid'));
|
||||||
|
} else {
|
||||||
|
return strings.formatString(strings.deviceDetails.connectionTypeWired, displayValue(client, 'ssid'));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
@@ -207,19 +238,19 @@ const DeviceDetails = props => {
|
|||||||
<View style={componentStyles.sectionDevice}>
|
<View style={componentStyles.sectionDevice}>
|
||||||
<ImageWithBadge
|
<ImageWithBadge
|
||||||
style={componentStyles.sectionDeviceIcon}
|
style={componentStyles.sectionDeviceIcon}
|
||||||
source={getClientIcon()}
|
source={getDeviceIcon()}
|
||||||
badgeSource={getClientBadgeIcon()}
|
badgeSource={getDeviceBadgeIcon()}
|
||||||
badgeTintColor={whiteColor}
|
badgeTintColor={whiteColor}
|
||||||
badgeBackgroundColor={getClientStatusColor()}
|
badgeBackgroundColor={getDeviceBadgeStatusColor()}
|
||||||
badgeSize="small"
|
badgeSize="large"
|
||||||
/>
|
/>
|
||||||
<Text style={componentStyles.sectionDeviceText}>{getClientName()}</Text>
|
<Text style={componentStyles.sectionDeviceText}>{getClientName()}</Text>
|
||||||
<ButtonStyled
|
<ButtonStyled
|
||||||
title={strings.buttons.pause}
|
title={onPauseUnpauseButtonLabel()}
|
||||||
type="outline"
|
type="outline"
|
||||||
onPress={onPausePress}
|
onPress={onPauseUnpausePress}
|
||||||
size="small"
|
size="small"
|
||||||
disabled={!client}
|
disabled={!device}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -228,7 +259,11 @@ const DeviceDetails = props => {
|
|||||||
title={strings.deviceDetails.connectionDetails}
|
title={strings.deviceDetails.connectionDetails}
|
||||||
disableAccordion={true}
|
disableAccordion={true}
|
||||||
isLoading={deviceLoading}>
|
isLoading={deviceLoading}>
|
||||||
<ItemTextWithLabel key="status" label={strings.deviceDetails.status} value="Connected" />
|
<ItemTextWithLabel
|
||||||
|
key="status"
|
||||||
|
label={strings.deviceDetails.status}
|
||||||
|
value={strings.deviceDetails.connected}
|
||||||
|
/>
|
||||||
<ItemTextWithLabel key="type" label={strings.deviceDetails.connectionType} value={getConnectionType()} />
|
<ItemTextWithLabel key="type" label={strings.deviceDetails.connectionType} value={getConnectionType()} />
|
||||||
</AccordionSection>
|
</AccordionSection>
|
||||||
|
|
||||||
@@ -237,44 +272,36 @@ const DeviceDetails = props => {
|
|||||||
title={strings.deviceDetails.deviceDetails}
|
title={strings.deviceDetails.deviceDetails}
|
||||||
disableAccordion={true}
|
disableAccordion={true}
|
||||||
isLoading={deviceLoading}>
|
isLoading={deviceLoading}>
|
||||||
<ItemTextWithLabel
|
<ItemTextWithLabel key="name" label={strings.deviceDetails.name} value={displayValue(device, 'name')} />
|
||||||
key="name"
|
|
||||||
label={strings.deviceDetails.name}
|
|
||||||
value={device ? device.name : strings.messages.empty}
|
|
||||||
/>
|
|
||||||
<ItemTextWithLabelEditable
|
<ItemTextWithLabelEditable
|
||||||
key="group"
|
key="group"
|
||||||
label={strings.deviceDetails.group}
|
label={strings.deviceDetails.group}
|
||||||
value={device ? device.group : strings.messages.empty}
|
value={displayValue(device, 'group')}
|
||||||
editKey="group"
|
editKey="group"
|
||||||
onEdit={updateDeviceValue}
|
onEdit={updateDeviceValue}
|
||||||
/>
|
/>
|
||||||
<ItemTextWithLabelEditable
|
<ItemTextWithLabelEditable
|
||||||
key="description"
|
key="description"
|
||||||
label={strings.deviceDetails.description}
|
label={strings.deviceDetails.description}
|
||||||
value={device ? device.description : strings.messages.empty}
|
value={displayValue(device, 'description')}
|
||||||
editKey="description"
|
editKey="description"
|
||||||
onEdit={updateDeviceValue}
|
onEdit={updateDeviceValue}
|
||||||
/>
|
/>
|
||||||
<ItemTextWithLabel
|
<ItemTextWithLabel key="type" label={strings.deviceDetails.type} value={displayValue(device, 'type')} />
|
||||||
key="type"
|
|
||||||
label={strings.deviceDetails.type}
|
|
||||||
value={device ? device.type : strings.messages.empty}
|
|
||||||
/>
|
|
||||||
<ItemTextWithLabel
|
<ItemTextWithLabel
|
||||||
key="manufacturer"
|
key="manufacturer"
|
||||||
label={strings.deviceDetails.manufacturer}
|
label={strings.deviceDetails.manufacturer}
|
||||||
value={device ? device.manufacturer : strings.messages.empty}
|
value={displayValue(device, 'manufacturer')}
|
||||||
/>
|
/>
|
||||||
<ItemTextWithLabel
|
<ItemTextWithLabel
|
||||||
key="ipAddress"
|
key="ipAddress"
|
||||||
label={strings.deviceDetails.ipAddress}
|
label={strings.deviceDetails.ipAddress}
|
||||||
value={device ? device.ip : strings.messages.empty}
|
value={displayValue(device, 'ip')}
|
||||||
/>
|
/>
|
||||||
<ItemTextWithLabel
|
<ItemTextWithLabel
|
||||||
key="macAddress"
|
key="macAddress"
|
||||||
label={strings.deviceDetails.macAddress}
|
label={strings.deviceDetails.macAddress}
|
||||||
value={device ? device.macAddress : strings.messages.empty}
|
value={displayValue(device, 'macAddress')}
|
||||||
/>
|
/>
|
||||||
</AccordionSection>
|
</AccordionSection>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user