onairos 2.0.7 → 2.0.9
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/SDK_MIGRATION_SUMMARY.md +140 -0
- package/dist/iframe.bundle.js +1 -1
- package/dist/iframe.bundle.js.map +1 -1
- package/dist/onairos.bundle.js +1 -1
- package/dist/onairos.bundle.js.map +1 -1
- package/dist/onairos.esm.js +1 -1
- package/dist/onairos.esm.js.map +1 -1
- package/onairos.d.ts +0 -182
- package/package.json +8 -18
- package/src/components/DataRequest.js +138 -127
- package/src/components/UniversalOnboarding.js +72 -18
- package/src/components/connectors/GmailConnector.js +177 -0
- package/src/components/connectors/InstagramConnector.js +171 -0
- package/src/components/connectors/LinkedInConnector.js +168 -0
- package/src/components/connectors/PinterestConnector.js +168 -0
- package/src/components/connectors/README.md +292 -0
- package/src/components/connectors/RedditConnector.js +168 -0
- package/src/components/connectors/YoutubeConnector.js +172 -0
- package/src/components/connectors/index.js +21 -0
- package/src/components/utils/UpdateConnections.js +43 -0
- package/src/iframe/DataRequestPage.jsx +5 -1
- package/src/index.js +0 -9
- package/src/onairos.jsx +0 -16
- package/src/onairosButton.jsx +2 -1
- package/src/overlay/overlay.js +1 -1
- package/src/sdk/LLMWrapper.js +0 -221
- package/src/sdk/MemoryManager.js +0 -290
- package/src/sdk/OnairosClient.js +0 -152
- package/src/sdk/SessionManager.js +0 -257
|
@@ -1,32 +1,48 @@
|
|
|
1
1
|
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import YoutubeConnector from './connectors/YoutubeConnector';
|
|
3
|
+
import LinkedInConnector from './connectors/LinkedInConnector';
|
|
4
|
+
import InstagramConnector from './connectors/InstagramConnector';
|
|
5
|
+
import PinterestConnector from './connectors/PinterestConnector';
|
|
6
|
+
import RedditConnector from './connectors/RedditConnector';
|
|
7
|
+
import GmailConnector from './connectors/GmailConnector';
|
|
2
8
|
|
|
3
9
|
const platforms = [
|
|
4
|
-
{ name: 'YouTube', icon: '📺', color: 'bg-red-500' },
|
|
5
|
-
{ name: 'Reddit', icon: '🔥', color: 'bg-orange-500' },
|
|
6
|
-
{ name: 'Instagram', icon: '📷', color: 'bg-pink-500' },
|
|
7
|
-
{ name: 'Pinterest', icon: '📌', color: 'bg-red-600' },
|
|
8
|
-
{ name: '
|
|
9
|
-
{ name: '
|
|
10
|
-
{ name: 'LinkedIn', icon: '💼', color: 'bg-blue-700' },
|
|
11
|
-
{ name: 'Facebook', icon: '👥', color: 'bg-blue-600' }
|
|
10
|
+
{ name: 'YouTube', icon: '📺', color: 'bg-red-500', connector: 'youtube' },
|
|
11
|
+
{ name: 'Reddit', icon: '🔥', color: 'bg-orange-500', connector: 'reddit' },
|
|
12
|
+
{ name: 'Instagram', icon: '📷', color: 'bg-pink-500', connector: 'instagram' },
|
|
13
|
+
{ name: 'Pinterest', icon: '📌', color: 'bg-red-600', connector: 'pinterest' },
|
|
14
|
+
{ name: 'LinkedIn', icon: '💼', color: 'bg-blue-700', connector: 'linkedin' },
|
|
15
|
+
{ name: 'Gmail', icon: '📧', color: 'bg-red-500', connector: 'gmail' }
|
|
12
16
|
];
|
|
13
17
|
|
|
14
|
-
export default function UniversalOnboarding({ onComplete, appIcon, appName = 'App' }) {
|
|
18
|
+
export default function UniversalOnboarding({ onComplete, appIcon, appName = 'App', username }) {
|
|
15
19
|
const [connectedAccounts, setConnectedAccounts] = useState({});
|
|
16
20
|
const [isConnecting, setIsConnecting] = useState(false);
|
|
21
|
+
const [activeConnector, setActiveConnector] = useState(null);
|
|
17
22
|
|
|
18
|
-
const
|
|
19
|
-
if (isConnecting) return;
|
|
20
|
-
|
|
21
|
-
setIsConnecting(true);
|
|
22
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
23
|
-
|
|
23
|
+
const handleConnectionChange = (platformName, isConnected) => {
|
|
24
24
|
setConnectedAccounts(prev => ({
|
|
25
25
|
...prev,
|
|
26
|
-
[platformName]:
|
|
26
|
+
[platformName]: isConnected
|
|
27
27
|
}));
|
|
28
|
+
setActiveConnector(null);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const handleToggle = async (platformName, connectorType) => {
|
|
32
|
+
if (isConnecting) return;
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
const isCurrentlyConnected = connectedAccounts[platformName];
|
|
35
|
+
|
|
36
|
+
if (isCurrentlyConnected) {
|
|
37
|
+
// Disconnect - call the connector's disconnect method
|
|
38
|
+
setConnectedAccounts(prev => ({
|
|
39
|
+
...prev,
|
|
40
|
+
[platformName]: false
|
|
41
|
+
}));
|
|
42
|
+
} else {
|
|
43
|
+
// Connect - open the OAuth dialog
|
|
44
|
+
setActiveConnector(connectorType);
|
|
45
|
+
}
|
|
30
46
|
};
|
|
31
47
|
|
|
32
48
|
const handleContinue = () => {
|
|
@@ -104,7 +120,7 @@ export default function UniversalOnboarding({ onComplete, appIcon, appName = 'Ap
|
|
|
104
120
|
|
|
105
121
|
{/* Toggle Switch */}
|
|
106
122
|
<button
|
|
107
|
-
onClick={() => handleToggle(platform.name)}
|
|
123
|
+
onClick={() => handleToggle(platform.name, platform.connector)}
|
|
108
124
|
disabled={isConnecting}
|
|
109
125
|
className={`relative inline-flex h-5 sm:h-6 w-9 sm:w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ${
|
|
110
126
|
isConnected ? 'bg-blue-600' : 'bg-gray-200'
|
|
@@ -151,6 +167,44 @@ export default function UniversalOnboarding({ onComplete, appIcon, appName = 'Ap
|
|
|
151
167
|
Skip for now
|
|
152
168
|
</button>
|
|
153
169
|
</div>
|
|
170
|
+
|
|
171
|
+
{/* OAuth Connector Dialogs */}
|
|
172
|
+
<YoutubeConnector
|
|
173
|
+
open={activeConnector === 'youtube'}
|
|
174
|
+
onClose={() => setActiveConnector(null)}
|
|
175
|
+
onConnectionChange={handleConnectionChange}
|
|
176
|
+
username={username}
|
|
177
|
+
/>
|
|
178
|
+
<LinkedInConnector
|
|
179
|
+
open={activeConnector === 'linkedin'}
|
|
180
|
+
onClose={() => setActiveConnector(null)}
|
|
181
|
+
onConnectionChange={handleConnectionChange}
|
|
182
|
+
username={username}
|
|
183
|
+
/>
|
|
184
|
+
<InstagramConnector
|
|
185
|
+
open={activeConnector === 'instagram'}
|
|
186
|
+
onClose={() => setActiveConnector(null)}
|
|
187
|
+
onConnectionChange={handleConnectionChange}
|
|
188
|
+
username={username}
|
|
189
|
+
/>
|
|
190
|
+
<PinterestConnector
|
|
191
|
+
open={activeConnector === 'pinterest'}
|
|
192
|
+
onClose={() => setActiveConnector(null)}
|
|
193
|
+
onConnectionChange={handleConnectionChange}
|
|
194
|
+
username={username}
|
|
195
|
+
/>
|
|
196
|
+
<RedditConnector
|
|
197
|
+
open={activeConnector === 'reddit'}
|
|
198
|
+
onClose={() => setActiveConnector(null)}
|
|
199
|
+
onConnectionChange={handleConnectionChange}
|
|
200
|
+
username={username}
|
|
201
|
+
/>
|
|
202
|
+
<GmailConnector
|
|
203
|
+
open={activeConnector === 'gmail'}
|
|
204
|
+
onClose={() => setActiveConnector(null)}
|
|
205
|
+
onConnectionChange={handleConnectionChange}
|
|
206
|
+
username={username}
|
|
207
|
+
/>
|
|
154
208
|
</div>
|
|
155
209
|
);
|
|
156
210
|
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
|
|
3
|
+
class GmailConnector extends Component {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.state = {
|
|
7
|
+
connected: false,
|
|
8
|
+
open: false,
|
|
9
|
+
isConnecting: false,
|
|
10
|
+
};
|
|
11
|
+
this.handleClose = this.handleClose.bind(this);
|
|
12
|
+
this.handleOpen = this.handleOpen.bind(this);
|
|
13
|
+
this.gmailConnect = this.gmailConnect.bind(this);
|
|
14
|
+
this.setConnected = this.setConnected.bind(this);
|
|
15
|
+
this.setDisconnected = this.setDisconnected.bind(this);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setConnected() {
|
|
19
|
+
this.setState({ connected: true });
|
|
20
|
+
if (this.props.onConnectionChange) {
|
|
21
|
+
this.props.onConnectionChange('Gmail', true);
|
|
22
|
+
}
|
|
23
|
+
this.handleClose();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setDisconnected() {
|
|
27
|
+
this.updateConnections('Remove', 'Gmail').then(() => {
|
|
28
|
+
this.setState({ connected: false });
|
|
29
|
+
if (this.props.onConnectionChange) {
|
|
30
|
+
this.props.onConnectionChange('Gmail', false);
|
|
31
|
+
}
|
|
32
|
+
this.handleClose();
|
|
33
|
+
}).catch((error) => {
|
|
34
|
+
console.error('Error removing Gmail connection:', error);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async updateConnections(updateType, newConnection) {
|
|
39
|
+
const jsonData = {
|
|
40
|
+
session: {
|
|
41
|
+
username: localStorage.getItem("username") || this.props.username
|
|
42
|
+
},
|
|
43
|
+
updateType,
|
|
44
|
+
newConnection
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch('https://api2.onairos.uk/connections/update', {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: {
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify(jsonData),
|
|
54
|
+
});
|
|
55
|
+
return await response.json();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('UpdateConnections error:', error);
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
handleOpen() {
|
|
63
|
+
this.setState({ open: true });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
handleClose() {
|
|
67
|
+
this.setState({ open: false });
|
|
68
|
+
if (this.props.onClose) {
|
|
69
|
+
this.props.onClose();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async gmailConnect() {
|
|
74
|
+
this.setState({ isConnecting: true });
|
|
75
|
+
|
|
76
|
+
const jsonData = {
|
|
77
|
+
session: {
|
|
78
|
+
username: localStorage.getItem("username") || this.props.username
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const response = await fetch('https://api2.onairos.uk/gmail/authorize', {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify(jsonData),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const result = await response.json();
|
|
92
|
+
|
|
93
|
+
if (result.gmailURL) {
|
|
94
|
+
window.location.href = result.gmailURL;
|
|
95
|
+
} else {
|
|
96
|
+
console.error('No Gmail URL received');
|
|
97
|
+
this.setState({ isConnecting: false });
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('Gmail connection error:', error);
|
|
101
|
+
this.setState({ isConnecting: false });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
const { open = this.props.open || this.state.open } = this.props;
|
|
107
|
+
|
|
108
|
+
if (!open) return null;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|
112
|
+
<div className="bg-white rounded-lg shadow-xl max-w-md w-full mx-4 max-h-[90vh] overflow-hidden">
|
|
113
|
+
<div className="p-6">
|
|
114
|
+
<h2 className="text-xl font-bold text-gray-900 mb-4">
|
|
115
|
+
Grant Onairos Access to your Gmail Account?
|
|
116
|
+
</h2>
|
|
117
|
+
|
|
118
|
+
<div className="space-y-4 text-gray-700">
|
|
119
|
+
<p>
|
|
120
|
+
Grant Permission to your Gmail Account, so we can build your Data Models.
|
|
121
|
+
</p>
|
|
122
|
+
|
|
123
|
+
<div>
|
|
124
|
+
<p className="font-medium mb-2">We will access your Gmail:</p>
|
|
125
|
+
<ul className="list-disc ml-6 space-y-1">
|
|
126
|
+
<li>Basic Account Information</li>
|
|
127
|
+
<li>Email Metadata (subjects, dates, senders)</li>
|
|
128
|
+
<li>Email Categories and Labels</li>
|
|
129
|
+
<li>Communication Patterns</li>
|
|
130
|
+
</ul>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-3">
|
|
134
|
+
<p className="text-yellow-800 text-sm font-medium">
|
|
135
|
+
<strong>Note:</strong> We do NOT read the content of your emails. Only metadata is processed.
|
|
136
|
+
</p>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<p>
|
|
140
|
+
We will delete all the data used once your Model is Created
|
|
141
|
+
</p>
|
|
142
|
+
|
|
143
|
+
<p className="text-sm">
|
|
144
|
+
<a href="https://onairos.uk/compliance-google-policy" className="text-blue-600 hover:underline">
|
|
145
|
+
Onairos
|
|
146
|
+
</a>{' '}
|
|
147
|
+
complies with{' '}
|
|
148
|
+
<a href="https://policies.google.com/privacy" className="text-blue-600 hover:underline">
|
|
149
|
+
Google API Services User Data Policy
|
|
150
|
+
</a>
|
|
151
|
+
</p>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div className="flex space-x-3 mt-6">
|
|
155
|
+
<button
|
|
156
|
+
onClick={this.handleClose}
|
|
157
|
+
disabled={this.state.isConnecting}
|
|
158
|
+
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 disabled:opacity-50"
|
|
159
|
+
>
|
|
160
|
+
Disagree
|
|
161
|
+
</button>
|
|
162
|
+
<button
|
|
163
|
+
onClick={this.gmailConnect}
|
|
164
|
+
disabled={this.state.isConnecting}
|
|
165
|
+
className="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
|
|
166
|
+
>
|
|
167
|
+
{this.state.isConnecting ? 'Connecting...' : 'Agree'}
|
|
168
|
+
</button>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export default GmailConnector;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
|
|
3
|
+
class InstagramConnector extends Component {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.state = {
|
|
7
|
+
connected: false,
|
|
8
|
+
open: false,
|
|
9
|
+
isConnecting: false,
|
|
10
|
+
};
|
|
11
|
+
this.handleClose = this.handleClose.bind(this);
|
|
12
|
+
this.handleOpen = this.handleOpen.bind(this);
|
|
13
|
+
this.instagramConnect = this.instagramConnect.bind(this);
|
|
14
|
+
this.setConnected = this.setConnected.bind(this);
|
|
15
|
+
this.setDisconnected = this.setDisconnected.bind(this);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setConnected() {
|
|
19
|
+
this.setState({ connected: true });
|
|
20
|
+
if (this.props.onConnectionChange) {
|
|
21
|
+
this.props.onConnectionChange('Instagram', true);
|
|
22
|
+
}
|
|
23
|
+
this.handleClose();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setDisconnected() {
|
|
27
|
+
this.updateConnections('Remove', 'Instagram').then(() => {
|
|
28
|
+
this.setState({ connected: false });
|
|
29
|
+
if (this.props.onConnectionChange) {
|
|
30
|
+
this.props.onConnectionChange('Instagram', false);
|
|
31
|
+
}
|
|
32
|
+
this.handleClose();
|
|
33
|
+
}).catch((error) => {
|
|
34
|
+
console.error('Error removing Instagram connection:', error);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async updateConnections(updateType, newConnection) {
|
|
39
|
+
const jsonData = {
|
|
40
|
+
session: {
|
|
41
|
+
username: localStorage.getItem("username") || this.props.username
|
|
42
|
+
},
|
|
43
|
+
updateType,
|
|
44
|
+
newConnection
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch('https://api2.onairos.uk/connections/update', {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: {
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify(jsonData),
|
|
54
|
+
});
|
|
55
|
+
return await response.json();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('UpdateConnections error:', error);
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
handleOpen() {
|
|
63
|
+
this.setState({ open: true });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
handleClose() {
|
|
67
|
+
this.setState({ open: false });
|
|
68
|
+
if (this.props.onClose) {
|
|
69
|
+
this.props.onClose();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async instagramConnect() {
|
|
74
|
+
this.setState({ isConnecting: true });
|
|
75
|
+
|
|
76
|
+
const jsonData = {
|
|
77
|
+
session: {
|
|
78
|
+
username: localStorage.getItem("username") || this.props.username
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const response = await fetch('https://api2.onairos.uk/instagram/authorize', {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify(jsonData),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const result = await response.json();
|
|
92
|
+
|
|
93
|
+
if (result.instagramURL) {
|
|
94
|
+
window.location.href = result.instagramURL;
|
|
95
|
+
} else {
|
|
96
|
+
console.error('No Instagram URL received');
|
|
97
|
+
this.setState({ isConnecting: false });
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('Instagram connection error:', error);
|
|
101
|
+
this.setState({ isConnecting: false });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
const { open = this.props.open || this.state.open } = this.props;
|
|
107
|
+
|
|
108
|
+
if (!open) return null;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|
112
|
+
<div className="bg-white rounded-lg shadow-xl max-w-md w-full mx-4 max-h-[90vh] overflow-hidden">
|
|
113
|
+
<div className="p-6">
|
|
114
|
+
<h2 className="text-xl font-bold text-gray-900 mb-4">
|
|
115
|
+
Grant Onairos Access to your Instagram Account?
|
|
116
|
+
</h2>
|
|
117
|
+
|
|
118
|
+
<div className="space-y-4 text-gray-700">
|
|
119
|
+
<p>
|
|
120
|
+
Grant Permission to your Instagram Account, so we can build your Data Models.
|
|
121
|
+
</p>
|
|
122
|
+
|
|
123
|
+
<div>
|
|
124
|
+
<p className="font-medium mb-2">We will access your Instagram:</p>
|
|
125
|
+
<ul className="list-disc ml-6 space-y-1">
|
|
126
|
+
<li>Basic Profile Information</li>
|
|
127
|
+
<li>Posts and Stories</li>
|
|
128
|
+
<li>Liked Content</li>
|
|
129
|
+
<li>Following and Followers</li>
|
|
130
|
+
</ul>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<p>
|
|
134
|
+
We will delete all the data used once your Model is Created
|
|
135
|
+
</p>
|
|
136
|
+
|
|
137
|
+
<p className="text-sm">
|
|
138
|
+
<a href="https://onairos.uk/compliance-meta-policy" className="text-blue-600 hover:underline">
|
|
139
|
+
Onairos
|
|
140
|
+
</a>{' '}
|
|
141
|
+
complies with{' '}
|
|
142
|
+
<a href="https://developers.facebook.com/policy" className="text-blue-600 hover:underline">
|
|
143
|
+
Meta Platform Policy
|
|
144
|
+
</a>
|
|
145
|
+
</p>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<div className="flex space-x-3 mt-6">
|
|
149
|
+
<button
|
|
150
|
+
onClick={this.handleClose}
|
|
151
|
+
disabled={this.state.isConnecting}
|
|
152
|
+
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 disabled:opacity-50"
|
|
153
|
+
>
|
|
154
|
+
Disagree
|
|
155
|
+
</button>
|
|
156
|
+
<button
|
|
157
|
+
onClick={this.instagramConnect}
|
|
158
|
+
disabled={this.state.isConnecting}
|
|
159
|
+
className="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
|
|
160
|
+
>
|
|
161
|
+
{this.state.isConnecting ? 'Connecting...' : 'Agree'}
|
|
162
|
+
</button>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export default InstagramConnector;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
|
|
3
|
+
class LinkedInConnector extends Component {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.state = {
|
|
7
|
+
connected: false,
|
|
8
|
+
open: false,
|
|
9
|
+
isConnecting: false,
|
|
10
|
+
};
|
|
11
|
+
this.handleClose = this.handleClose.bind(this);
|
|
12
|
+
this.handleOpen = this.handleOpen.bind(this);
|
|
13
|
+
this.linkedinConnect = this.linkedinConnect.bind(this);
|
|
14
|
+
this.setConnected = this.setConnected.bind(this);
|
|
15
|
+
this.setDisconnected = this.setDisconnected.bind(this);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setConnected() {
|
|
19
|
+
this.setState({ connected: true });
|
|
20
|
+
if (this.props.onConnectionChange) {
|
|
21
|
+
this.props.onConnectionChange('LinkedIn', true);
|
|
22
|
+
}
|
|
23
|
+
this.handleClose();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setDisconnected() {
|
|
27
|
+
this.updateConnections('Remove', 'LinkedIn').then(() => {
|
|
28
|
+
this.setState({ connected: false });
|
|
29
|
+
if (this.props.onConnectionChange) {
|
|
30
|
+
this.props.onConnectionChange('LinkedIn', false);
|
|
31
|
+
}
|
|
32
|
+
this.handleClose();
|
|
33
|
+
}).catch((error) => {
|
|
34
|
+
console.error('Error removing LinkedIn connection:', error);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async updateConnections(updateType, newConnection) {
|
|
39
|
+
const jsonData = {
|
|
40
|
+
session: {
|
|
41
|
+
username: localStorage.getItem("username") || this.props.username
|
|
42
|
+
},
|
|
43
|
+
updateType,
|
|
44
|
+
newConnection
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch('https://api2.onairos.uk/connections/update', {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: {
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify(jsonData),
|
|
54
|
+
});
|
|
55
|
+
return await response.json();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('UpdateConnections error:', error);
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
handleOpen() {
|
|
63
|
+
this.setState({ open: true });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
handleClose() {
|
|
67
|
+
this.setState({ open: false });
|
|
68
|
+
if (this.props.onClose) {
|
|
69
|
+
this.props.onClose();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async linkedinConnect() {
|
|
74
|
+
this.setState({ isConnecting: true });
|
|
75
|
+
|
|
76
|
+
const jsonData = {
|
|
77
|
+
session: {
|
|
78
|
+
username: localStorage.getItem("username") || this.props.username
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const response = await fetch('https://api2.onairos.uk/linkedin/authorize', {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify(jsonData),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const result = await response.json();
|
|
92
|
+
|
|
93
|
+
if (result.linkedinURL) {
|
|
94
|
+
window.location.href = result.linkedinURL;
|
|
95
|
+
} else {
|
|
96
|
+
console.error('No LinkedIn URL received');
|
|
97
|
+
this.setState({ isConnecting: false });
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('LinkedIn connection error:', error);
|
|
101
|
+
this.setState({ isConnecting: false });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
const { open = this.props.open || this.state.open } = this.props;
|
|
107
|
+
|
|
108
|
+
if (!open) return null;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|
112
|
+
<div className="bg-white rounded-lg shadow-xl max-w-md w-full mx-4 max-h-[90vh] overflow-hidden">
|
|
113
|
+
<div className="p-6">
|
|
114
|
+
<h2 className="text-xl font-bold text-gray-900 mb-4">
|
|
115
|
+
Grant Onairos Access to your LinkedIn Account?
|
|
116
|
+
</h2>
|
|
117
|
+
|
|
118
|
+
<div className="space-y-4 text-gray-700">
|
|
119
|
+
<p>
|
|
120
|
+
Grant Permission to your LinkedIn Account, so we can build your Data Models.
|
|
121
|
+
</p>
|
|
122
|
+
|
|
123
|
+
<div>
|
|
124
|
+
<p className="font-medium mb-2">We will access your LinkedIn:</p>
|
|
125
|
+
<ul className="list-disc ml-6 space-y-1">
|
|
126
|
+
<li>Basic Profile Information</li>
|
|
127
|
+
<li>Professional Experience</li>
|
|
128
|
+
<li>Network Connections</li>
|
|
129
|
+
<li>Posts and Activity</li>
|
|
130
|
+
</ul>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<p>
|
|
134
|
+
We will delete all the data used once your Model is Created
|
|
135
|
+
</p>
|
|
136
|
+
|
|
137
|
+
<p className="text-sm">
|
|
138
|
+
<a href="https://onairos.uk/privacy-policy" className="text-blue-600 hover:underline">
|
|
139
|
+
Onairos Privacy Policy
|
|
140
|
+
</a>{' '}
|
|
141
|
+
- Your professional data is handled with the highest security standards.
|
|
142
|
+
</p>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<div className="flex space-x-3 mt-6">
|
|
146
|
+
<button
|
|
147
|
+
onClick={this.handleClose}
|
|
148
|
+
disabled={this.state.isConnecting}
|
|
149
|
+
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 disabled:opacity-50"
|
|
150
|
+
>
|
|
151
|
+
Disagree
|
|
152
|
+
</button>
|
|
153
|
+
<button
|
|
154
|
+
onClick={this.linkedinConnect}
|
|
155
|
+
disabled={this.state.isConnecting}
|
|
156
|
+
className="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
|
|
157
|
+
>
|
|
158
|
+
{this.state.isConnecting ? 'Connecting...' : 'Agree'}
|
|
159
|
+
</button>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export default LinkedInConnector;
|