rendering registry response

This commit is contained in:
Roland Osborne 2022-03-28 23:56:02 -07:00
parent 7a8403e34a
commit 20ad55f252
9 changed files with 175 additions and 25 deletions

View File

@ -12,6 +12,10 @@ export function getProfileImageUrl(token, revision) {
return '/profile/image?agent=' + token + "&revision=" + revision
}
export function getListingImageUrl(server, guid, revision) {
return `https://${server}/account/listing/${guid}/image?revision=${revision}`
}
async function fetchWithTimeout(url, options) {
return Promise.race([
fetch(url, options).catch(err => { throw new Error(url + ' failed'); }),
@ -88,3 +92,9 @@ export async function getGroups(token, revision) {
return await groups.json()
}
export async function getListing(server) {
let listing = await fetchWithTimeout(`https://${server}/account/listing`, { method: 'GET', timeout: FETCH_TIMEOUT });
checkResponse(listing);
return await listing.json();
}

View File

@ -1,5 +1,5 @@
import { useEffect, useState, useRef } from 'react';
import { setProfileImage, setProfileData, getProfileImageUrl, getAccountStatus, setAccountSearchable, getProfile, getGroups, getAvailable, getUsername, setLogin, createAccount } from './fetchUtil';
import { getListingImageUrl, getListing, setProfileImage, setProfileData, getProfileImageUrl, getAccountStatus, setAccountSearchable, getProfile, getGroups, getAvailable, getUsername, setLogin, createAccount } from './fetchUtil';
async function updateAccount(token, updateData) {
let status = await getAccountStatus(token);
@ -86,7 +86,9 @@ export function useAppContext() {
setAccountSearchable: async (flag) => {
await setAccountSearchable(state.token, flag);
},
profileImageUrl: () => getProfileImageUrl(state.token, state.Data?.profile?.revision)
profileImageUrl: () => getProfileImageUrl(state.token, state.Data?.profile?.revision),
getRegistry: async (node) => getListing(node),
getRegistryImageUrl: (server, guid, revision) => getListingImageUrl(server, guid, revision),
}
const adminActions = {

22
net/web/src/Logo/Logo.jsx Normal file
View File

@ -0,0 +1,22 @@
import React, { useState } from 'react'
import { UserOutlined } from '@ant-design/icons';
import { LogoWrapper } from './Logo.styled';
export function Logo({ imageSet, imageUrl }) {
if (imageUrl == null) {
return <></>
} else if (!imageSet) {
return (
<LogoWrapper>
<UserOutlined />
</LogoWrapper>
)
} else {
return (
<LogoWrapper>
<img class='logo' src={ imageUrl } alt='' />
</LogoWrapper>
);
}
}

View File

@ -0,0 +1,19 @@
import styled from 'styled-components';
export const LogoWrapper = styled.div`
border-radius: 4px;
overflow: hidden;
width: 100%;
height: 100%;
display: flex;
font-size: 24px;
color: #888888;
align-items: center;
justify-content: center;
.logo {
width: 100%;
height: 100%;
}
`;

View File

@ -1,12 +1,39 @@
import React from 'react';
import { RegistryWrapper } from './Registry.styled';
import { Input } from 'antd';
import { useRegistry } from './useRegistry.hook';
import { Button, Input, List } from 'antd';
import { Logo } from '../../../../../Logo/Logo';
import { MoreOutlined } from '@ant-design/icons';
export function Registry() {
const { state, actions } = useRegistry();
return (
<RegistryWrapper>
<Input.Search placeholder="Server" allowClear style={{ width: '100%' }} />
<div class="contacts" />
<Input.Search placeholder="Server" value={state.server} onChange={(e) => actions.setServer(e.target.Value)}
onSearch={actions.getRegistry} style={{ width: '100%' }} />
<div class="contacts">
<List
locale={{ emptyText: '' }}
itemLayout="horizontal"
dataSource={state.profiles}
renderItem={item => (
<List.Item>
<div class="item">
<div class="logo">
<Logo imageUrl={actions.getRegistryImageUrl(item.guid, item.revision)}
imageSet={item.imageSet} />
</div>
<div class="username">
<span class="name">{ item.name }</span>
<span class="handle">{ item.handle }</span>
</div>
</div>
</List.Item>
)}
/>
</div>
</RegistryWrapper>
);
}

View File

@ -6,7 +6,6 @@ export const RegistryWrapper = styled.div`
padding-right: 8px;
text-align: center;
display: flex;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
flex-direction: column;
@ -16,7 +15,39 @@ export const RegistryWrapper = styled.div`
background-color: #fefefe;
border-radius-bottom-right: 8px;
border-radius-bottom-left: 8px;
height: calc(100vh - 174px);
overflow: auto;
}
.item {
width: 100%;
display: flex;
padding-left: 16px;
flex-direction: row;
align-items: center;
}
.logo {
width: 36px;
height: 36px;
}
.username {
display: flex;
flex-direction: column;
padding-left: 16px;
text-align: left;
flex-grow: 1;
}
.name {
font-size: 1em;
}
.handle {
font-size: 0.9em;
font-weight: bold;
}
`;

View File

@ -0,0 +1,51 @@
import { useContext, useState, useEffect } from 'react';
import { AppContext } from '../../../../../AppContext/AppContext';
import { useNavigate } from "react-router-dom";
export function useRegistry() {
const [state, setState] = useState({
server: '',
busy: false,
profiles: [],
});
const app = useContext(AppContext);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (app?.state?.Data?.profile) {
let profile = app.state.Data.profile;
updateState({ server: profile.node });
}
}, [app]);
const actions = {
setServer: (server) => {
updateState({ server: server });
},
getRegistry: async () => {
if (!state.busy && state.server != '') {
updateState({ busy: true });
try {
let profiles = await app.actions.getRegistry(state.server)
updateState({ profiles: profiles });
console.log(profiles);
}
catch (err) {
window.alert(err)
}
updateState({ busy: false });
}
},
getRegistryImageUrl: (guid, revision) => app.actions.getRegistryImageUrl(state.server, guid, revision),
}
return { state, actions };
}

View File

@ -4,22 +4,12 @@ import { IdentityWrapper, IdentityDropdown, MenuWrapper } from './Identity.style
import { RightOutlined, EditOutlined, UserOutlined } from '@ant-design/icons';
import { useIdentity } from './useIdentity.hook';
import { Menu, Dropdown } from 'antd';
import { Logo } from '../../../Logo/Logo';
export function Identity() {
const { state, actions } = useIdentity()
const Logo = () => {
console.log(state);
if (state.imageUrl != null) {
if (state.imageUrl === '') {
return <UserOutlined />
}
return <img class="logo" src={ state.imageUrl } alt="" />
}
return <></>
}
const menu = (
<MenuWrapper>
<Menu.Item key="0">
@ -39,7 +29,7 @@ console.log(state);
<IdentityDropdown overlay={menu} overlayStyle={{ minWidth: 0 }} trigger={['click']} placement="rightTop">
<div class="container">
<div class="avatar">
<Logo />
<Logo imageSet={state.image!=null} imageUrl={state.imageUrl} />
</div>
<div class="username">
<span class="name">{ state.name }</span>

View File

@ -8,7 +8,8 @@ export function useIdentity() {
name: '',
handle: '',
domain: '',
imageUrl: null
imageUrl: null,
image: null,
});
const actions = {
@ -33,11 +34,8 @@ export function useIdentity() {
useEffect(() => {
if (app?.state?.Data?.profile) {
let profile = app.state.Data.profile;
if (profile.image != null && profile.image != '') {
updateState({ imageUrl: app.actions.profileImageUrl() })
} else {
updateState({ imageUrl: '' })
}
updateState({ imageUrl: app.actions.profileImageUrl() })
updateState({ image: profile.image });
updateState({ name: profile.name });
updateState({ handle: profile.handle });
updateState({ domain: profile.node });