linked-data-browser 0.0.1 → 0.0.3

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/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # Linked Data Browser (LDB)
2
2
 
3
- This codebase is for a data browser UI for Solid servers.
3
+ This codebase is for a data browser UI for Solid servers.
@@ -15,9 +15,10 @@ import {
15
15
  DialogDescription,
16
16
  DialogClose,
17
17
  } from '../ui/dialog';
18
- import { TextInput, View } from 'react-native';
18
+ import { View } from 'react-native';
19
19
  import { Button } from '../ui/button';
20
20
  import { Text } from '../ui/text';
21
+ import { Input } from '../ui/input';
21
22
 
22
23
  type DialogOptions =
23
24
  | { type: 'confirm'; title: string; message?: string }
@@ -112,7 +113,7 @@ export const DialogProvider: React.FC<{ children: React.ReactNode }> = ({
112
113
 
113
114
  {options?.type === 'prompt' && (
114
115
  <View className="my-2">
115
- <TextInput
116
+ <Input
116
117
  value={inputValue}
117
118
  onChangeText={setInputValue}
118
119
  placeholder="Enter text..."
@@ -16,6 +16,7 @@ import { Header } from './header/Header';
16
16
  import { View } from 'react-native';
17
17
  import { useValidView, ValidViewProvider } from './useValidView';
18
18
  import { DialogProvider } from './DialogProvider';
19
+ import { useSolidAuth } from '@ldo/solid-react';
19
20
 
20
21
  export const ValidViewContext = createContext<{
21
22
  validViews: ResourceViewConfig[];
@@ -25,6 +26,12 @@ export const ValidViewContext = createContext<{
25
26
  }>({});
26
27
 
27
28
  export const Layout: FunctionComponent = () => {
29
+ const { ranInitialAuthCheck } = useSolidAuth();
30
+
31
+ if (!ranInitialAuthCheck) {
32
+ return <></>;
33
+ }
34
+
28
35
  return (
29
36
  <DialogProvider>
30
37
  <ValidViewProvider>
@@ -1,62 +1,86 @@
1
+ import {
2
+ useLdo,
3
+ useResource,
4
+ useSolidAuth,
5
+ useSubject,
6
+ } from '@ldo/solid-react';
1
7
  import React from 'react';
2
-
3
8
  import { FunctionComponent } from 'react';
4
- import { StyleSheet } from 'react-native';
9
+ import { View } from 'react-native';
10
+ import { SolidProfileShapeShapeType } from '../../../.ldo/profile.shapeTypes';
11
+ import { Avatar, AvatarFallback, AvatarImage } from '../../ui/avatar';
12
+ import { Text } from '../../ui/text';
13
+ import { Button } from '../../ui/button';
14
+ import { ThemeToggleMenu } from './ThemeToggleMenu';
15
+ import {
16
+ DropdownMenu,
17
+ DropdownMenuContent,
18
+ DropdownMenuItem,
19
+ DropdownMenuSeparator,
20
+ DropdownMenuTrigger,
21
+ } from '../../ui/dropdown-menu';
22
+ import { User } from '../../../lib/icons/User';
23
+ import { LogOut } from '../../../lib/icons/LogOut';
24
+ import { useTargetResource } from '../../TargetResourceProvider';
5
25
 
6
26
  export const AvatarMenu: FunctionComponent = () => {
7
- return <></>;
8
- // const [menuVisible, setMenuVisible] = useState(false);
9
- // const { session, logout } = useSolidAuth();
10
- // // TODO: Use WebId Resource to render a skeleton loader
11
- // const webIdResource = useResource(session.webId);
12
- // const profile = useSubject(SolidProfileShapeShapeType, session.webId);
13
- // const renderAvatar = () => (
14
- // <TouchableWithoutFeedback onPress={() => setMenuVisible(true)}>
15
- // <Avatar
16
- // source={{ uri: 'https://api.lorem.space/image/face?w=150&h=150' }}
17
- // />
18
- // </TouchableWithoutFeedback>
19
- // );
20
- // return (
21
- // <Popover
22
- // anchor={renderAvatar}
23
- // visible={menuVisible}
24
- // placement="bottom end"
25
- // onBackdropPress={() => setMenuVisible(false)}
26
- // style={styles.popover}
27
- // >
28
- // <Layout>
29
- // <View style={styles.profileHeader}>
30
- // <Avatar
31
- // size="giant"
32
- // source={{ uri: 'https://api.lorem.space/image/face?w=150&h=150' }}
33
- // />
34
- // <View style={styles.profileText}>
35
- // <Text category="h6">{profile?.fn || ''}</Text>
36
- // <Button size="tiny">Edit your profile</Button>
37
- // </View>
38
- // </View>
39
- // <Divider />
40
- // <ThemeToggleMenu />
41
- // <Divider />
42
- // <MenuItem
43
- // onPress={logout}
44
- // title="Log Out"
45
- // accessoryLeft={(props) => <Icon {...props} name="log-out" />}
46
- // />
47
- // </Layout>
48
- // </Popover>
49
- // );
50
- };
27
+ const { dataset } = useLdo();
28
+ const { session, logout } = useSolidAuth();
29
+ // TODO: Use WebId Resource to render a skeleton loader
30
+ const webIdResource = useResource(session.webId);
31
+ const profile = useSubject(SolidProfileShapeShapeType, session.webId);
32
+ const { navigateTo } = useTargetResource();
33
+
34
+ if (!session.webId) return <></>;
51
35
 
52
- const styles = StyleSheet.create({
53
- popover: { width: 300, overflow: 'hidden', borderRadius: 12 },
54
- profileHeader: { padding: 8, flexDirection: 'row', alignItems: 'center' },
55
- profileText: {
56
- marginLeft: 8,
57
- justifyContent: 'space-around',
58
- alignSelf: 'stretch',
59
- alignItems: 'flex-start',
60
- flex: 1,
61
- },
62
- });
36
+ console.log(profile?.['@id']);
37
+ console.log(profile?.hasPhoto?.['@id']);
38
+ console.log(webIdResource?.isLoading());
39
+ console.log(dataset.toString());
40
+
41
+ return (
42
+ <DropdownMenu>
43
+ <DropdownMenuTrigger asChild>
44
+ <Button key="setMemu" variant="ghost" className="w-10">
45
+ <Avatar alt={profile?.fn ? `${profile.fn}'s Avatar` : ''}>
46
+ <AvatarImage source={{ uri: profile?.hasPhoto?.['@id'] }} />
47
+ <AvatarFallback>
48
+ <Text>
49
+ <User />
50
+ </Text>
51
+ </AvatarFallback>
52
+ </Avatar>
53
+ </Button>
54
+ </DropdownMenuTrigger>
55
+ <DropdownMenuContent className="w-64 native:w-72 mr-2 mt-2">
56
+ <View className="p-2 flex-row items-center">
57
+ <Avatar
58
+ alt={profile?.fn ? `${profile.fn}'s Avatar` : ''}
59
+ className="w-20 h-20"
60
+ >
61
+ <AvatarImage source={{ uri: profile?.hasPhoto?.['@id'] }} />
62
+ <AvatarFallback>
63
+ <Text>
64
+ <User />
65
+ </Text>
66
+ </AvatarFallback>
67
+ </Avatar>
68
+ <View className="ml-2">
69
+ <Text>{profile?.fn || ''}</Text>
70
+ <Button size="sm" onPress={() => navigateTo(session.webId ?? '')}>
71
+ <Text>Edit your profile</Text>
72
+ </Button>
73
+ </View>
74
+ </View>
75
+ <DropdownMenuSeparator />
76
+ <ThemeToggleMenu />
77
+ <DropdownMenuSeparator />
78
+ <DropdownMenuItem onPress={logout}>
79
+ <Text className="flex flex-row gap-1 items-center">
80
+ <LogOut /> Log Out
81
+ </Text>
82
+ </DropdownMenuItem>
83
+ </DropdownMenuContent>
84
+ </DropdownMenu>
85
+ );
86
+ };
File without changes
package/infra/hosts ADDED
@@ -0,0 +1,2 @@
1
+ [web]
2
+ 34.66.140.216 ansible_user=jackson
@@ -0,0 +1,2 @@
1
+ [web]
2
+ your-server-ip ansible_user=ubuntu
@@ -0,0 +1,12 @@
1
+ server {
2
+ listen 80;
3
+ server_name {{ domain }};
4
+ location / {
5
+ proxy_pass http://localhost:3000;
6
+ proxy_http_version 1.1;
7
+ proxy_set_header Upgrade $http_upgrade;
8
+ proxy_set_header Connection 'upgrade';
9
+ proxy_set_header Host $host;
10
+ proxy_cache_bypass $http_upgrade;
11
+ }
12
+ }
@@ -0,0 +1,77 @@
1
+ - name: Deploy Node Git Server
2
+ hosts: web
3
+ become: yes
4
+
5
+ vars:
6
+ docker_image: "jaxoncreed/integration-pod:latest"
7
+
8
+ vars_files:
9
+ - secrets.yml
10
+
11
+ tasks:
12
+ - name: Install required packages
13
+ apt:
14
+ name:
15
+ - docker.io
16
+ - docker-compose
17
+ - nginx
18
+ - certbot
19
+ - python3-certbot-nginx
20
+ update_cache: yes
21
+
22
+ - name: Enable Docker service
23
+ systemd:
24
+ name: docker
25
+ enabled: yes
26
+ state: started
27
+
28
+ - name: Log in to Docker Hub
29
+ docker_login:
30
+ registry_url: https://index.docker.io/v1/
31
+ username: "{{ dockerhub_username }}"
32
+ password: "{{ dockerhub_password }}"
33
+
34
+ - name: Pull Docker image
35
+ docker_image:
36
+ name: "{{ docker_image }}"
37
+ source: pull
38
+
39
+ - name: Run container
40
+ docker_container:
41
+ name: server
42
+ image: "{{ docker_image }}"
43
+ state: started
44
+ restart_policy: always
45
+ ports:
46
+ - "3000:3000"
47
+
48
+ - name: Set up NGINX config
49
+ template:
50
+ src: nginx.conf.j2
51
+ dest: /etc/nginx/sites-available/server
52
+ notify:
53
+ - Reload nginx
54
+
55
+ - name: Enable site
56
+ file:
57
+ src: /etc/nginx/sites-available/server
58
+ dest: /etc/nginx/sites-enabled/server
59
+ state: link
60
+ force: true
61
+
62
+ - name: Remove default site
63
+ file:
64
+ path: /etc/nginx/sites-enabled/default
65
+ state: absent
66
+
67
+ - name: Obtain SSL cert
68
+ command: >
69
+ certbot --nginx -d {{ domain }} --non-interactive --agree-tos -m {{ email }}
70
+ args:
71
+ creates: "/etc/letsencrypt/live/{{ domain }}"
72
+
73
+ handlers:
74
+ - name: Reload nginx
75
+ service:
76
+ name: nginx
77
+ state: reloaded
@@ -0,0 +1,11 @@
1
+ $ANSIBLE_VAULT;1.1;AES256
2
+ 66363662346539366434346433653035333336306162626463336363356639346663336438313331
3
+ 3066616236343234333865626233313230396661333865300a623962646230303839643136333039
4
+ 66323262396437616333613434303932343462366266323732633439356362373566313062313037
5
+ 6337366430376162340a323464316363366439663531373661343339303662633239343762643234
6
+ 32353164633332623839353562633932303162323535316665633936623638326234353035663638
7
+ 62303032393362623438303064653336343766663737353066656131386436613539353262343562
8
+ 61336563346561373762633839396163636530316239616561303338353135373137333235366332
9
+ 31383865393732366165393538333839623065336161336335353334393365323965363136333231
10
+ 62623635376134316366653630653037343133323566373335323430646362303031383036336139
11
+ 6266383137663536623064346636626436623333613566366233
@@ -0,0 +1,4 @@
1
+ import { LogOut } from 'lucide-react-native';
2
+ import { iconWithClassName } from './iconWithClassName';
3
+ iconWithClassName(LogOut);
4
+ export { LogOut };
@@ -0,0 +1,4 @@
1
+ import { User } from 'lucide-react-native';
2
+ import { iconWithClassName } from './iconWithClassName';
3
+ iconWithClassName(User);
4
+ export { User };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "linked-data-browser",
3
3
  "main": "index.js",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "scripts": {
6
6
  "dev:ios": "expo start -c --ios",
7
7
  "dev:web": "concurrently \"npm run solid-server\" \"expo start -c --web\"",
@@ -17,10 +17,10 @@
17
17
  "build": "npm run build:standalone && npm run build:server"
18
18
  },
19
19
  "dependencies": {
20
- "@inrupt/solid-client-authn-browser": "^2.5.0",
21
- "@ldo/connected-solid": "^1.0.0-alpha.26",
22
- "@ldo/ldo": "^1.0.0-alpha.21",
23
- "@ldo/solid-react": "^1.0.0-alpha.26",
20
+ "@inrupt/solid-client-authn-browser": "^3.0.0",
21
+ "@ldo/connected-solid": "^1.0.0-alpha.27",
22
+ "@ldo/ldo": "^1.0.0-alpha.27",
23
+ "@ldo/solid-react": "^1.0.0-alpha.27",
24
24
  "@monaco-editor/react": "^4.7.0",
25
25
  "@radix-ui/react-dialog": "^1.1.14",
26
26
  "@radix-ui/react-dropdown-menu": "^2.1.15",
@@ -16,6 +16,7 @@ export const RawCodeView: FunctionComponent = () => {
16
16
  const { targetUri } = useTargetResource();
17
17
  const { fetch } = useSolidAuth();
18
18
  const [content, setContent] = useState<string>('');
19
+ const [contentType, setContentType] = useState<string>('');
19
20
 
20
21
  // Independently fetch the target resource, so we have the raw turtle
21
22
  const fetchContent = useCallback(async () => {
@@ -27,12 +28,16 @@ export const RawCodeView: FunctionComponent = () => {
27
28
  });
28
29
  }
29
30
  setContent(await response.text());
31
+ setContentType(response.headers.get('content-type') ?? '');
30
32
  }, [fetch, targetUri]);
31
33
 
32
34
  const submitChanges = useCallback(async () => {
33
35
  if (!targetUri) return;
34
36
  const response = await fetch(targetUri, {
35
37
  method: 'put',
38
+ headers: {
39
+ 'content-type': contentType,
40
+ },
36
41
  body: content,
37
42
  });
38
43
  if (response.status !== 205) {
@@ -44,7 +49,7 @@ export const RawCodeView: FunctionComponent = () => {
44
49
  title: `Document Saved`,
45
50
  });
46
51
  await fetchContent();
47
- }, [content, fetch, fetchContent, targetUri]);
52
+ }, [content, contentType, fetch, fetchContent, targetUri]);
48
53
 
49
54
  useEffect(() => {
50
55
  fetchContent();