Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
unigraph.getState('global/omnibarSummoner').setValue({
show: true,
show: !unigraph.getState('global/omnibarSummoner').value?.show,
tooltip: '',
defaultValue: '',
});
1 change: 1 addition & 0 deletions packages/unigraph-dev-backend/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,7 @@ export default async function startServer(client: DgraphClient) {
};

await Promise.all(Object.values(caches).map((el: Cache<any>) => el.updateNow()));
updateClientCache(serverStates, 'schemaMap', serverStates.caches.schemas.data);

initEntityHeads(
serverStates,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const createBookmark = async (text: string, add = true) => {
return {
name,
children: tags.map((tagName) => ({
type: { 'unigraph.id': '$/schema/subentity' },
type: { 'unigraph.id': '$/schema/interface/semantic' },
_value: {
type: { 'unigraph.id': '$/schema/tag' },
name: tagName,
Expand Down
45 changes: 6 additions & 39 deletions packages/unigraph-dev-explorer/src/examples/notes/NoteEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import { parseUnigraphHtml } from '../../clipboardUtils';
import { getParentsAndReferences } from '../../components/ObjectView/backlinksUtils';
import { inlineTextSearch, inlineObjectSearch } from '../../components/UnigraphCore/InlineSearchPopup';
import { debounce, scrollIntoViewIfNeeded, selectUid, setCaret, TabContext } from '../../utils';
import {
GetChangesForAutoComplete,
changesForOpenScopedChar,
changesForOpenScopedMarkdownLink,
} from '../../utils/autocomplete';
import { htmlToMarkdown } from '../semantic/Markdown';
import { permanentlyDeleteBlock } from './commands';
import { addTextualCommand, applyCommand } from './history';
Expand All @@ -29,45 +34,6 @@ const TextareaAutosizeStyled = styled(TextareaAutosize)(({ theme }) => ({
},
}));

type ScopeForAutoComplete = { currentText: string; caret: number; middle: string; end: string };
type ChangesForAutoComplete = { newText: string; newCaret: number; newCaretOffset: number };
type GetChangesForAutoComplete = (scope: ScopeForAutoComplete, ev: KeyboardEvent) => ChangesForAutoComplete;

const changesForOpenScopedChar = (
{ currentText, caret, middle, end }: ScopeForAutoComplete,
ev: KeyboardEvent,
): ChangesForAutoComplete => {
const isChar = (c: string) => c !== ' ' && c !== '\n' && c !== '\t' && c !== undefined;
const nextChar = currentText?.[caret];
const shouldNotOpen = middle.length === 0 && isChar(nextChar) && nextChar !== closeScopeCharDict[ev.key];

return {
newText: `${currentText.slice(0, caret)}${ev.key}${middle}${
shouldNotOpen ? '' : closeScopeCharDict[ev.key]
}${end}${currentText.slice(caret + (middle + end).length)}`,
newCaret: caret + 1,
newCaretOffset: middle.length,
};
};
const changesForOpenScopedMarkdownLink = (scope: ScopeForAutoComplete, ev: KeyboardEvent): ChangesForAutoComplete => {
const { currentText, caret, middle, end } = scope;

if (isUrl(middle)) {
return {
newText: `${currentText.slice(0, caret)}[](${middle})${end}${currentText.slice(
caret + (middle + end).length,
)}`,
newCaret: caret + 1,
newCaretOffset: 0,
};
}
return {
newText: `${currentText.slice(0, caret)}[${middle}]()${end}${currentText.slice(caret + (middle + end).length)}`,
newCaret: caret + middle.length + 3,
newCaretOffset: 0,
};
};

const touchParents = (data: any) => {
const [parents] = getParentsAndReferences(data['~_value'], data['unigraph.origin']);
if (!data._hide) parents.push({ uid: data.uid });
Expand Down Expand Up @@ -426,6 +392,7 @@ export const useNoteEditor: (...args: any) => [any, (text: string) => void, () =
[callbacks],
);

// TODO: merge all these into autocomplete.ts in utils
const handleScopedAutoComplete = React.useCallback(
(changeTextAndCaret: GetChangesForAutoComplete, ev: KeyboardEvent) => {
ev.preventDefault();
Expand Down
43 changes: 22 additions & 21 deletions packages/unigraph-dev-explorer/src/examples/semantic/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,30 @@ const addPage = async (childrenRoot: any, newName: any, subsId: any) => {
},
'$/schema/note_block',
);
window.unigraph.updateObject(
childrenRoot.uid,
{
_value: {
children: {
'_value[': [
{
_key: `[[${newName}]]`,
_value: {
'dgraph.type': ['Interface'],
type: { 'unigraph.id': '$/schema/interface/semantic' },
_hide: true,
_value: { uid: newUid[0] },
if (childrenRoot.uid)
window.unigraph.updateObject(
childrenRoot.uid,
{
_value: {
children: {
'_value[': [
{
_key: `[[${newName}]]`,
_value: {
'dgraph.type': ['Interface'],
type: { 'unigraph.id': '$/schema/interface/semantic' },
_hide: true,
_value: { uid: newUid[0] },
},
},
},
],
],
},
},
},
},
true,
false,
subsId,
);
true,
false,
subsId,
);
return newUid[0];
};

Expand All @@ -103,7 +104,7 @@ const tryFindLinkToAdd = async (childrenRoot: any, name: string, subsId: any) =>
}`,
]);
const linkFound = res[0].sort((a: any, b: any) => b.popularity - a.popularity)[0];
if (linkFound) {
if (linkFound && childrenRoot.uid) {
console.log('k');
window.unigraph.updateObject(
childrenRoot.uid,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { getContrast } from '../../utils';

const getBgColor = (tag: any) => (tag?.color?.startsWith && tag.color.startsWith('#') ? tag.color : 'unset');
export const Tag: DynamicViewRenderer = ({ data, callbacks }) => {
const [tag, setTag] = React.useState(() => (data._value ? unpad(data) : data));
const tag = data._value ? unpad(data) : data;

return (
<Chip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ const quickAdder = async (
refs?: any,
) => {
const parsed = parseTodoObject(inputStr, refs);
console.log(parsed);
if (!preview) {
// eslint-disable-next-line no-return-await
const uid = await window.unigraph.addObject(parsed, '$/schema/todo');
Expand Down
9 changes: 7 additions & 2 deletions packages/unigraph-dev-explorer/src/init.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ export function init(hostname?: string) {
browserId,
};

// Set up basic anonymized analytics by default
if (window.localStorage.getItem('enableAnalytics') === null) {
window.localStorage.setItem('enableAnalytics', 'true');
}

let userSettings = defaultSettings;

if (!isJsonString(window.localStorage.getItem('userSettings'))) {
Expand Down Expand Up @@ -297,10 +302,10 @@ function initBacklinkManager() {
}

/**
* Initializes analytics when user explicitly opted in.
* Initializes analytics depends on user opt-in status
*
* Information we collect:
* - basic info: time, email (user-given), browser, os, country
* - basic info: time, email (user-given, with explicit permission), browser, os, country
* - user actions: click, keypress - anonimized into 15 second chunks
*
* We use them to calculate session length and usage frequency.
Expand Down
62 changes: 36 additions & 26 deletions packages/unigraph-dev-explorer/src/pages/SearchOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AutoDynamicView } from '../components/ObjectView/AutoDynamicView';
import { inlineTextSearch } from '../components/UnigraphCore/InlineSearchPopup';
import { parseQuery } from '../components/UnigraphCore/UnigraphSearch';
import { isElectron, trivialTypes, typeHasDynamicView } from '../utils';
import { handleOpenScopedChar } from '../utils/autocomplete';

const groups = [
{
Expand Down Expand Up @@ -40,33 +41,32 @@ function AdderComponent({ input, setInput, open, setClose, callback, summonerToo
if (allAdders[parsedInput.key]) {
allAdders[parsedInput.key].adder(parsedInput.val).then((res: any) => {
const [object, type] = res;
window.unigraph.getSchemas().then((schemas: any) => {
try {
const padded = buildUnigraphEntity(JSON.parse(JSON.stringify(object)), type, schemas);
setToAdd(
<div
onClickCapture={(ev) => {
ev.stopPropagation();
const schemas = (window.unigraph as any).getSchemaMap();
try {
const padded = buildUnigraphEntity(JSON.parse(JSON.stringify(object)), type, schemas);
setToAdd(
<div
onClickCapture={(ev) => {
ev.stopPropagation();
}}
>
<AutoDynamicView
object={new UnigraphObject(padded)}
options={{ noDrag: true, noDrop: true, noClickthrough: true }}
style={{
border: 'gray',
borderStyle: 'dashed',
borderWidth: 'thin',
margin: '2px',
borderRadius: '8px',
padding: '4px',
}}
>
<AutoDynamicView
object={new UnigraphObject(padded)}
options={{ noDrag: true, noDrop: true, noClickthrough: true }}
style={{
border: 'gray',
borderStyle: 'dashed',
borderWidth: 'thin',
margin: '2px',
borderRadius: '8px',
padding: '4px',
}}
/>
</div>,
);
} catch (e) {
console.log(e);
}
});
/>
</div>,
);
} catch (e) {
console.log(e);
}
});
}
}, [parsedInput]);
Expand All @@ -83,6 +83,12 @@ function AdderComponent({ input, setInput, open, setClose, callback, summonerToo
}}
inputRef={tf}
value={input}
onKeyDown={(ev) => {
if (ev.key === '[')
handleOpenScopedChar(ev as any, tf, input, (ipt: string) => {
setInput(ipt);
});
}}
onChange={(ev) => {
const newContent = ev.target.value;
const caret = ev.target.selectionStart || 0;
Expand Down Expand Up @@ -392,6 +398,10 @@ export function SearchOverlayPopover({ open, setClose, noShadow }: any) {
else setSearchEnabled(false);
}, [summonerState]);

React.useEffect(() => {
setSearchEnabled(!!summonerState.show);
}, [summonerState]);

React.useEffect(() => {
if (searchEnabled) {
const listener = (event: MouseEvent) => {
Expand Down
63 changes: 49 additions & 14 deletions packages/unigraph-dev-explorer/src/pages/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,32 +95,67 @@ export default function Settings() {
<ListSubheader component="div" id="nested-list-subheader" key="analyticsHeader">
Analytics
</ListSubheader>
<ListItem
sx={{ ...pointerHoverSx, display: analyticsMode ? '' : 'none' }}
onClick={(e) => false}
key="analyticsOptedIn"
>
<ListItemText
id="switch-list-label-analytics-optin-mode"
primary="Opt out of analytics"
secondary="Switch to opt out of analytics. To opt in again, enter your email below."
/>
<ListItemSecondaryAction style={{ display: analyticsMode ? '' : 'none' }}>
<Switch
edge="end"
onChange={(e) => {
analyticsState.setValue(!analyticsMode);
}}
checked={analyticsMode}
inputProps={{
'aria-labelledby': 'switch-list-label-optin-analytics-mode',
}}
/>
</ListItemSecondaryAction>
</ListItem>
<ListItem sx={pointerHoverSx} onClick={(e) => false} key="analytics">
<ListItemText
id="switch-list-label-analytics-mode"
primary="Enable analytics"
primary={!analyticsMode ? 'Enable analytics' : 'Update email'}
secondary={
<span>
Opt-in to analytics with mixpanel by entering your email address.
<br />
We will only record your usage length and basic information (OS, country).
</span>
!analyticsMode ? (
<span>
Opt-in to analytics by clicking &quot;Opt-in&quot;. <br />
Optionally, you can enter your email address before clicking to associate your
analytics information with your email.
<br />
We will only record your usage length and basic information (OS, country).
</span>
) : (
<span>
Associate your analytics information with your email (optional). <br />
This will allow us to understand how you use Unigraph, and contact you when things
are broken.
</span>
)
}
/>
<ListItemSecondaryAction>
<TextField value={email} onChange={(ev) => setEmail(ev.target.value)} />
<Button
onClick={() => {
analyticsState.setValue(email.length !== 0);
window.localStorage.setItem('email', email);
(window as any).mixpanel.identify(email);
(window as any).mixpanel.people.set({
$name: email,
$email: email,
});
analyticsState.setValue(true);
if (email.length > 0) {
window.localStorage.setItem('email', email);
(window as any).mixpanel.identify(email);
(window as any).mixpanel.people.set({
$name: email,
$email: email,
});
}
}}
>
Opt-in
{!analyticsMode ? 'Opt-in' : 'Update email'}
</Button>
</ListItemSecondaryAction>
</ListItem>
Expand Down
Loading