mirror of
https://github.com/ecency/ecency-mobile.git
synced 2025-01-07 14:41:16 +03:00
Merge pull request #2494 from ecency/nt/use-query-snippets
Nt/use query snippets
This commit is contained in:
commit
cd939241e3
@ -1,5 +1,6 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { TouchableOpacity, ActivityIndicator } from 'react-native';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
import { Icon } from '../../icon';
|
||||
|
||||
import styles from './iconButtonStyles';
|
||||
@ -47,7 +48,10 @@ const IconButton = ({
|
||||
badgeCount={badgeCount}
|
||||
/>
|
||||
) : (
|
||||
<ActivityIndicator color="white" style={styles.activityIndicator} />
|
||||
<ActivityIndicator
|
||||
color={color || EStyleSheet.value('$primaryBlack')}
|
||||
style={styles.activityIndicator}
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</Fragment>
|
||||
|
@ -4,166 +4,143 @@ import { Alert, KeyboardAvoidingView, Platform, View } from 'react-native';
|
||||
import { TextInput } from '..';
|
||||
import { ThemeContainer } from '../../containers';
|
||||
import { Snippet } from '../../models';
|
||||
import { addFragment, updateFragment} from '../../providers/ecency/ecency';
|
||||
import { useSnippetsMutation } from '../../providers/queries';
|
||||
import { TextButton } from '../buttons';
|
||||
import Modal from '../modal';
|
||||
import styles from './snippetEditorModalStyles';
|
||||
|
||||
|
||||
export interface SnippetEditorModalRef {
|
||||
showNewModal:()=>void;
|
||||
showEditModal:(snippet:Snippet)=>void;
|
||||
showNewModal: () => void;
|
||||
showEditModal: (snippet: Snippet) => void;
|
||||
}
|
||||
|
||||
interface SnippetEditorModalProps {
|
||||
onSnippetsUpdated:(snips:Array<Snippet>)=>void;
|
||||
}
|
||||
const SnippetEditorModal = ({}, ref) => {
|
||||
const intl = useIntl();
|
||||
const titleInputRef = useRef(null);
|
||||
const bodyInputRef = useRef(null);
|
||||
|
||||
const SnippetEditorModal = ({onSnippetsUpdated}: SnippetEditorModalProps, ref) => {
|
||||
const intl = useIntl();
|
||||
const titleInputRef = useRef(null);
|
||||
const bodyInputRef = useRef(null);
|
||||
const snippetsMutation = useSnippetsMutation();
|
||||
|
||||
const [title, setTitle] = useState('');
|
||||
const [body, setBody] = useState('');
|
||||
const [snippetId, setSnippetId] = useState<string|null>(null);
|
||||
const [isNewSnippet, setIsNewSnippet] = useState(true);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [titleHeight, setTitleHeight] = useState(0)
|
||||
const [title, setTitle] = useState('');
|
||||
const [body, setBody] = useState('');
|
||||
const [snippetId, setSnippetId] = useState<string | null>(null);
|
||||
const [isNewSnippet, setIsNewSnippet] = useState(true);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [titleHeight, setTitleHeight] = useState(0);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
showNewModal: () => {
|
||||
setTitle('');
|
||||
setBody('');
|
||||
setIsNewSnippet(true);
|
||||
setShowModal(true);
|
||||
},
|
||||
showEditModal:(snippet:Snippet)=>{
|
||||
setSnippetId(snippet.id);
|
||||
setTitle(snippet.title);
|
||||
setBody(snippet.body);
|
||||
setIsNewSnippet(false);
|
||||
setShowModal(true);
|
||||
}
|
||||
}));
|
||||
useImperativeHandle(ref, () => ({
|
||||
showNewModal: () => {
|
||||
setTitle('');
|
||||
setBody('');
|
||||
setIsNewSnippet(true);
|
||||
setShowModal(true);
|
||||
},
|
||||
showEditModal: (snippet: Snippet) => {
|
||||
setSnippetId(snippet.id);
|
||||
setTitle(snippet.title);
|
||||
setBody(snippet.body);
|
||||
setIsNewSnippet(false);
|
||||
setShowModal(true);
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
//save snippet based on editor type
|
||||
const _saveSnippet = async () => {
|
||||
try{
|
||||
if(!title || !body){
|
||||
Alert.alert(intl.formatMessage({id:'snippets.message_incomplete'}));
|
||||
return;
|
||||
}
|
||||
|
||||
let response = [];
|
||||
if(!isNewSnippet){
|
||||
console.log("Updating snippet:", snippetId, title, body)
|
||||
response = await updateFragment(snippetId, title, body);
|
||||
console.log("Response from add snippet: ", response)
|
||||
}else{
|
||||
console.log("Saving snippet:", title, body)
|
||||
const res = await addFragment(title, body)
|
||||
response = res && res.fragments
|
||||
console.log("Response from add snippet: ", response)
|
||||
}
|
||||
setShowModal(false);
|
||||
onSnippetsUpdated(response);
|
||||
|
||||
}catch(err){
|
||||
Alert.alert(intl.formatMessage({id:'snippets.message_failed'}))
|
||||
console.warn("Failed to save snippet", err)
|
||||
}
|
||||
|
||||
//save snippet based on editor type
|
||||
const _saveSnippet = async () => {
|
||||
if (!title || !body) {
|
||||
Alert.alert(intl.formatMessage({ id: 'snippets.message_incomplete' }));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Saving snippet:', title, body);
|
||||
|
||||
const _renderContent = (
|
||||
<ThemeContainer>
|
||||
{({isDarkTheme})=>(
|
||||
<KeyboardAvoidingView
|
||||
style={styles.container}
|
||||
keyboardVerticalOffset={Platform.OS == 'ios' ? 64 : null}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : null}
|
||||
>
|
||||
<View style={styles.inputContainer}>
|
||||
snippetsMutation.mutate({
|
||||
id: isNewSnippet ? null : snippetId,
|
||||
title,
|
||||
body,
|
||||
});
|
||||
|
||||
|
||||
<View style={{height:Math.max(35, titleHeight)}}>
|
||||
<TextInput
|
||||
autoFocus={true}
|
||||
innerRef={titleInputRef}
|
||||
style={styles.titleInput}
|
||||
height={Math.max(35, titleHeight)}
|
||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||
maxLength={250}
|
||||
placeholder={intl.formatMessage({id:'snippets.placeholder_title'})}
|
||||
multiline
|
||||
numberOfLines={2}
|
||||
onContentSizeChange={(event) => {
|
||||
setTitleHeight(event.nativeEvent.contentSize.height);
|
||||
}}
|
||||
onChangeText={setTitle}
|
||||
value={title}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<TextInput
|
||||
multiline
|
||||
autoCorrect={true}
|
||||
value={body}
|
||||
onChangeText={setBody}
|
||||
placeholder={intl.formatMessage({id:'snippets.placeholder_body'})}
|
||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||
selectionColor="#357ce6"
|
||||
style={styles.bodyWrapper}
|
||||
underlineColorAndroid="transparent"
|
||||
innerRef={bodyInputRef}
|
||||
autoGrow={false}
|
||||
scrollEnabled={false}
|
||||
height={100}
|
||||
/>
|
||||
</View>
|
||||
setShowModal(false);
|
||||
};
|
||||
|
||||
|
||||
<View style={styles.actionPanel}>
|
||||
<TextButton
|
||||
text={intl.formatMessage({id:'snippets.btn_close'})}
|
||||
onPress={()=>setShowModal(false)}
|
||||
style={styles.closeButton}
|
||||
/>
|
||||
<TextButton
|
||||
text={intl.formatMessage({id:'snippets.btn_save'})}
|
||||
onPress={_saveSnippet}
|
||||
textStyle={styles.btnText}
|
||||
style={styles.saveButton}
|
||||
/>
|
||||
</View>
|
||||
|
||||
</KeyboardAvoidingView>
|
||||
)}
|
||||
</ThemeContainer>
|
||||
)
|
||||
const _renderContent = (
|
||||
<ThemeContainer>
|
||||
{({ isDarkTheme }) => (
|
||||
<KeyboardAvoidingView
|
||||
style={styles.container}
|
||||
keyboardVerticalOffset={Platform.OS == 'ios' ? 64 : null}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : null}
|
||||
>
|
||||
<View style={styles.inputContainer}>
|
||||
<View style={{ height: Math.max(35, titleHeight) }}>
|
||||
<TextInput
|
||||
autoFocus={true}
|
||||
innerRef={titleInputRef}
|
||||
style={styles.titleInput}
|
||||
height={Math.max(35, titleHeight)}
|
||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||
maxLength={250}
|
||||
placeholder={intl.formatMessage({ id: 'snippets.placeholder_title' })}
|
||||
multiline
|
||||
numberOfLines={2}
|
||||
onContentSizeChange={(event) => {
|
||||
setTitleHeight(event.nativeEvent.contentSize.height);
|
||||
}}
|
||||
onChangeText={setTitle}
|
||||
value={title}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<TextInput
|
||||
multiline
|
||||
autoCorrect={true}
|
||||
value={body}
|
||||
onChangeText={setBody}
|
||||
placeholder={intl.formatMessage({ id: 'snippets.placeholder_body' })}
|
||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||
selectionColor="#357ce6"
|
||||
style={styles.bodyWrapper}
|
||||
underlineColorAndroid="transparent"
|
||||
innerRef={bodyInputRef}
|
||||
autoGrow={false}
|
||||
scrollEnabled={false}
|
||||
height={100}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.actionPanel}>
|
||||
<TextButton
|
||||
text={intl.formatMessage({ id: 'snippets.btn_close' })}
|
||||
onPress={() => setShowModal(false)}
|
||||
style={styles.closeButton}
|
||||
/>
|
||||
<TextButton
|
||||
text={intl.formatMessage({ id: 'snippets.btn_save' })}
|
||||
onPress={_saveSnippet}
|
||||
textStyle={styles.btnText}
|
||||
style={styles.saveButton}
|
||||
/>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
)}
|
||||
</ThemeContainer>
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={showModal}
|
||||
handleOnModalClose={()=>{setShowModal(false)}}
|
||||
presentationStyle="formSheet"
|
||||
title={intl.formatMessage({
|
||||
id:isNewSnippet
|
||||
? 'snippets.title_add_snippet'
|
||||
: 'snippets.title_edit_snippet'
|
||||
})}
|
||||
animationType="slide"
|
||||
style={styles.modalStyle}
|
||||
>
|
||||
{_renderContent}
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
isOpen={showModal}
|
||||
handleOnModalClose={() => {
|
||||
setShowModal(false);
|
||||
}}
|
||||
presentationStyle="formSheet"
|
||||
title={intl.formatMessage({
|
||||
id: isNewSnippet ? 'snippets.title_add_snippet' : 'snippets.title_edit_snippet',
|
||||
})}
|
||||
animationType="slide"
|
||||
style={styles.modalStyle}
|
||||
>
|
||||
{_renderContent}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default forwardRef(SnippetEditorModal);
|
||||
|
||||
|
||||
|
@ -1,43 +1,72 @@
|
||||
import * as React from 'react';
|
||||
import { Text, View, Button } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Alert, Text, View } from 'react-native';
|
||||
import { useSnippetDeleteMutation } from '../../providers/queries';
|
||||
import IconButton from '../iconButton';
|
||||
import styles from './snippetsModalStyles';
|
||||
|
||||
interface SnippetItemProps {
|
||||
title:string;
|
||||
body:string;
|
||||
index:number;
|
||||
onEditPress:()=>void;
|
||||
onRemovePress:()=>void;
|
||||
id: string | null;
|
||||
title: string;
|
||||
body: string;
|
||||
index: number;
|
||||
onEditPress: () => void;
|
||||
}
|
||||
|
||||
const SnippetItem = ({title, body, index, onEditPress, onRemovePress}: SnippetItemProps) => {
|
||||
const SnippetItem = ({ id, title, body, index, onEditPress }: SnippetItemProps) => {
|
||||
const intl = useIntl();
|
||||
const snippetsDeleteMutation = useSnippetDeleteMutation();
|
||||
|
||||
const _onRemovePress = () => {
|
||||
//asks for remvoe confirmation and run remove routing upon confirming
|
||||
if (id) {
|
||||
Alert.alert(
|
||||
intl.formatMessage({ id: 'snippets.title_remove_confirmation' }),
|
||||
intl.formatMessage({ id: 'snippets.message_remove_confirmation' }),
|
||||
[
|
||||
{
|
||||
text: intl.formatMessage({ id: 'snippets.btn_cancel' }),
|
||||
style: 'cancel',
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage({ id: 'snippets.btn_confirm' }),
|
||||
onPress: () => snippetsDeleteMutation.mutate(id),
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={[styles.itemWrapper, index % 2 !== 0 && styles.itemWrapperGray]}>
|
||||
<View style={styles.itemHeader}>
|
||||
<Text style={styles.title} numberOfLines={1} >{`${title}`}</Text>
|
||||
<IconButton
|
||||
iconStyle={styles.itemIcon}
|
||||
style={styles.itemIconWrapper}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="pencil"
|
||||
onPress={onEditPress}
|
||||
size={20}
|
||||
/>
|
||||
<IconButton
|
||||
iconStyle={styles.itemIcon}
|
||||
style={styles.itemIconWrapper}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="delete"
|
||||
onPress={onRemovePress}
|
||||
size={20}
|
||||
/>
|
||||
<Text style={styles.title} numberOfLines={1}>{`${title}`}</Text>
|
||||
{id && (
|
||||
<>
|
||||
<IconButton
|
||||
iconStyle={styles.itemIcon}
|
||||
style={styles.itemIconWrapper}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="pencil"
|
||||
onPress={onEditPress}
|
||||
size={20}
|
||||
/>
|
||||
<IconButton
|
||||
iconStyle={styles.itemIcon}
|
||||
style={styles.itemIconWrapper}
|
||||
isLoading={snippetsDeleteMutation.isLoading}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="delete"
|
||||
onPress={_onRemovePress}
|
||||
size={20}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
||||
|
||||
<Text style={styles.body} numberOfLines={2} ellipsizeMode="tail">{`${body}`}</Text>
|
||||
|
||||
</View>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export default SnippetItem;
|
||||
export default SnippetItem;
|
||||
|
@ -1,172 +1,106 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { View, FlatList, Text, TouchableOpacity, Alert } from 'react-native';
|
||||
import React, { useRef } from 'react';
|
||||
import { View, FlatList, Text, TouchableOpacity, Alert, RefreshControl } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { getFragments, deleteFragment } from '../../providers/ecency/ecency';
|
||||
import { deleteFragment } from '../../providers/ecency/ecency';
|
||||
import { MainButton } from '..';
|
||||
import styles from './snippetsModalStyles';
|
||||
import { RefreshControl } from 'react-native';
|
||||
import SnippetEditorModal, { SnippetEditorModalRef } from '../snippetEditorModal/snippetEditorModal';
|
||||
|
||||
import SnippetEditorModal, {
|
||||
SnippetEditorModalRef,
|
||||
} from '../snippetEditorModal/snippetEditorModal';
|
||||
import SnippetItem from './snippetItem';
|
||||
import { Snippet } from '../../models';
|
||||
import { useAppSelector } from '../../hooks';
|
||||
import { useSnippetDeleteMutation, useSnippetsQuery } from '../../providers/queries';
|
||||
|
||||
interface SnippetsModalProps {
|
||||
handleOnSelect:(snippetText:string)=>void,
|
||||
handleOnSelect: (snippetText: string) => void;
|
||||
}
|
||||
|
||||
const SnippetsModal = ({ handleOnSelect }:SnippetsModalProps) => {
|
||||
const SnippetsModal = ({ handleOnSelect }: SnippetsModalProps) => {
|
||||
const editorRef = useRef<SnippetEditorModalRef>(null);
|
||||
const intl = useIntl();
|
||||
|
||||
const isLoggedIn = useAppSelector(state => state.application.isLoggedIn)
|
||||
|
||||
const [snippets, setSnippets] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
_getSnippets();
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
//fetch snippets from server
|
||||
const _getSnippets = async () => {
|
||||
try{
|
||||
|
||||
setIsLoading(true);
|
||||
const snips = await getFragments()
|
||||
console.log("snips received", snips)
|
||||
setSnippets(snips);
|
||||
setIsLoading(false);
|
||||
|
||||
}catch(err){
|
||||
console.warn("Failed to get snippets")
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
//removes snippet from users snippet collection on user confirmation
|
||||
const _removeSnippet = async (id:string) => {
|
||||
try{
|
||||
|
||||
setIsLoading(true);
|
||||
const snips = await deleteFragment(id)
|
||||
setSnippets(snips);
|
||||
setIsLoading(false);
|
||||
|
||||
}catch(err){
|
||||
console.warn("Failed to get snippets")
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn);
|
||||
|
||||
const snippetsQuery = useSnippetsQuery();
|
||||
|
||||
//render list item for snippet and handle actions;
|
||||
const _renderItem = ({ item, index }:{item:Snippet, index:number}) => {
|
||||
|
||||
const _onPress = () => handleOnSelect(item.body)
|
||||
|
||||
//asks for remvoe confirmation and run remove routing upon confirming
|
||||
const _onRemovePress = () => {
|
||||
Alert.alert(
|
||||
intl.formatMessage({id:'snippets.title_remove_confirmation'}),
|
||||
intl.formatMessage({id:'snippets.message_remove_confirmation'}),
|
||||
[
|
||||
{
|
||||
text:intl.formatMessage({id:'snippets.btn_cancel'}),
|
||||
style:'cancel'
|
||||
},
|
||||
{
|
||||
text:intl.formatMessage({id:'snippets.btn_confirm'}),
|
||||
onPress:()=>_removeSnippet(item.id)
|
||||
}
|
||||
]
|
||||
)
|
||||
}
|
||||
const _renderItem = ({ item, index }: { item: Snippet; index: number }) => {
|
||||
const _onPress = () => handleOnSelect(item.body);
|
||||
|
||||
const _onEditPress = () => {
|
||||
if(editorRef.current){
|
||||
if (editorRef.current) {
|
||||
editorRef.current.showEditModal(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={_onPress}>
|
||||
<SnippetItem
|
||||
title={item.title}
|
||||
body={item.body}
|
||||
index={index}
|
||||
onEditPress={_onEditPress}
|
||||
onRemovePress={_onRemovePress}
|
||||
/>
|
||||
<SnippetItem
|
||||
id={item.id}
|
||||
title={item.title}
|
||||
body={item.body}
|
||||
index={index}
|
||||
onEditPress={_onEditPress}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//render empty list placeholder
|
||||
const _renderEmptyContent = () => {
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.title}>{intl.formatMessage({id:'snippets.label_no_snippets'})}</Text>
|
||||
<Text style={styles.title}>{intl.formatMessage({ id: 'snippets.label_no_snippets' })}</Text>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//renders footer with add snipept button and shows new snippet modal
|
||||
const _renderFloatingButton = () => {
|
||||
if(!isLoggedIn){
|
||||
if (!isLoggedIn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
const _onPress = () => {
|
||||
if(editorRef.current){
|
||||
if (editorRef.current) {
|
||||
editorRef.current.showNewModal();
|
||||
}
|
||||
}
|
||||
};
|
||||
return (
|
||||
<View style={styles.floatingContainer}>
|
||||
<MainButton
|
||||
style={{ width: 150}}
|
||||
style={{ width: 150 }}
|
||||
onPress={_onPress}
|
||||
iconName="plus"
|
||||
iconType="MaterialCommunityIcons"
|
||||
iconColor="white"
|
||||
text={intl.formatMessage({id:'snippets.btn_add'})}
|
||||
text={intl.formatMessage({ id: 'snippets.btn_add' })}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.bodyWrapper}>
|
||||
<FlatList
|
||||
data={snippets}
|
||||
data={snippetsQuery.data}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={_renderItem}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={isLoading}
|
||||
onRefresh={_getSnippets}
|
||||
<RefreshControl
|
||||
refreshing={snippetsQuery.isFetching}
|
||||
onRefresh={snippetsQuery.refetch}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
{_renderFloatingButton()}
|
||||
|
||||
</View>
|
||||
|
||||
<SnippetEditorModal
|
||||
ref={editorRef}
|
||||
onSnippetsUpdated={setSnippets}
|
||||
/>
|
||||
<SnippetEditorModal ref={editorRef} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
ReceivedVestingShare,
|
||||
Referral,
|
||||
ReferralStat,
|
||||
Snippet,
|
||||
} from './ecency.types';
|
||||
|
||||
/**
|
||||
@ -326,7 +327,7 @@ export const deleteFavorite = async (targetUsername: string) => {
|
||||
export const getFragments = async () => {
|
||||
try {
|
||||
const response = await ecencyApi.post('/private-api/fragments');
|
||||
return response.data;
|
||||
return response.data as Snippet[];
|
||||
} catch (error) {
|
||||
console.warn('Failed to get fragments', error);
|
||||
bugsnagInstance.notify(error);
|
||||
|
@ -1,59 +1,66 @@
|
||||
import { QuoteItem } from "../../redux/reducers/walletReducer";
|
||||
import { QuoteItem } from '../../redux/reducers/walletReducer';
|
||||
|
||||
export interface ReceivedVestingShare {
|
||||
delegator:string;
|
||||
delegatee:string;
|
||||
vesting_shares:string;
|
||||
timestamp:string;
|
||||
delegator: string;
|
||||
delegatee: string;
|
||||
vesting_shares: string;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface Snippet {
|
||||
id: string;
|
||||
title: string;
|
||||
body: string;
|
||||
created: string;
|
||||
modified: string;
|
||||
}
|
||||
|
||||
export interface EcencyUser {
|
||||
username:string;
|
||||
points:string;
|
||||
unclaimed_points:string;
|
||||
points_by_type:{[key:string]:string};
|
||||
unclaimed_points_by_type:{[key:string]:string};
|
||||
username: string;
|
||||
points: string;
|
||||
unclaimed_points: string;
|
||||
points_by_type: { [key: string]: string };
|
||||
unclaimed_points_by_type: { [key: string]: string };
|
||||
}
|
||||
|
||||
export interface Referral {
|
||||
id:number;
|
||||
referral:string;
|
||||
rewarded:boolean;
|
||||
username:string;
|
||||
created:string
|
||||
id: number;
|
||||
referral: string;
|
||||
rewarded: boolean;
|
||||
username: string;
|
||||
created: string;
|
||||
}
|
||||
|
||||
export interface ReferralStat {
|
||||
total: number;
|
||||
rewarded: number;
|
||||
total: number;
|
||||
rewarded: number;
|
||||
}
|
||||
|
||||
export interface UserPoint {
|
||||
id: number;
|
||||
type: number;
|
||||
amount: string;
|
||||
created:string;
|
||||
memo?: string;
|
||||
receiver?: string;
|
||||
sender?: string;
|
||||
|
||||
id: number;
|
||||
type: number;
|
||||
amount: string;
|
||||
created: string;
|
||||
memo?: string;
|
||||
receiver?: string;
|
||||
sender?: string;
|
||||
}
|
||||
|
||||
export interface LatestQuotes {
|
||||
[key:string]:QuoteItem
|
||||
[key: string]: QuoteItem;
|
||||
}
|
||||
|
||||
export interface CommentHistoryItem {
|
||||
body: string;
|
||||
tags: [string];
|
||||
title: string;
|
||||
timestamp:string;
|
||||
v: number;
|
||||
body: string;
|
||||
tags: [string];
|
||||
title: string;
|
||||
timestamp: string;
|
||||
v: number;
|
||||
}
|
||||
|
||||
export enum ScheduledPostStatus {
|
||||
PENDING = 1,
|
||||
POSTPONED = 2,
|
||||
PUBLISHED = 3,
|
||||
ERROR = 4,
|
||||
}
|
||||
PENDING = 1,
|
||||
POSTPONED = 2,
|
||||
PUBLISHED = 3,
|
||||
ERROR = 4,
|
||||
}
|
||||
|
90
src/providers/queries/editorQueries.ts
Normal file
90
src/providers/queries/editorQueries.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useAppDispatch } from '../../hooks';
|
||||
import { toastNotification } from '../../redux/actions/uiAction';
|
||||
import { addFragment, deleteFragment, getFragments, updateFragment } from '../ecency/ecency';
|
||||
import { Snippet } from '../ecency/ecency.types';
|
||||
import QUERIES from './queryKeys';
|
||||
|
||||
interface SnippetMutationVars {
|
||||
id: string | null;
|
||||
title: string;
|
||||
body: string;
|
||||
}
|
||||
|
||||
export const useSnippetsQuery = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
return useQuery<Snippet[]>([QUERIES.SNIPPETS.GET], getFragments, {
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSnippetsMutation = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<Snippet[], undefined, SnippetMutationVars>(
|
||||
async (vars) => {
|
||||
console.log('going to add/update snippet', vars);
|
||||
if (vars.id) {
|
||||
const response = await updateFragment(vars.id, vars.title, vars.body);
|
||||
return response;
|
||||
} else {
|
||||
const response = await addFragment(vars.title, vars.body);
|
||||
return response;
|
||||
}
|
||||
},
|
||||
{
|
||||
onMutate: (vars) => {
|
||||
console.log('mutate snippets for add/update', vars);
|
||||
|
||||
const _newItem = {
|
||||
id: vars.id,
|
||||
title: vars.title,
|
||||
body: vars.body,
|
||||
created: new Date().toDateString(),
|
||||
modified: new Date().toDateString(),
|
||||
} as Snippet;
|
||||
|
||||
const data = queryClient.getQueryData<Snippet[]>([QUERIES.SNIPPETS.GET]);
|
||||
|
||||
let _newData: Snippet[] = data ? [...data] : [];
|
||||
if (vars.id) {
|
||||
const snipIndex = _newData.findIndex((item) => vars.id === item.id);
|
||||
_newData[snipIndex] = _newItem;
|
||||
} else {
|
||||
_newData = [_newItem, ..._newData];
|
||||
}
|
||||
|
||||
queryClient.setQueryData([QUERIES.SNIPPETS.GET], _newData);
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
console.log('added/updated snippet', data);
|
||||
queryClient.invalidateQueries([QUERIES.SNIPPETS.GET]);
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'snippets.message_failed' })));
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const useSnippetDeleteMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation<Snippet[], undefined, string>(deleteFragment, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log('Success scheduled post delete', data);
|
||||
queryClient.setQueryData([QUERIES.SNIPPETS.GET], data);
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
@ -22,3 +22,5 @@ export const initQueryClient = () => {
|
||||
persistOptions: { persister: asyncStoragePersister },
|
||||
} as PersistQueryClientProviderProps;
|
||||
};
|
||||
|
||||
export * from './editorQueries';
|
||||
|
@ -5,6 +5,9 @@ const QUERIES = {
|
||||
SCHEDULES: {
|
||||
GET: 'QUERY_GET_SCHEDULES',
|
||||
},
|
||||
SNIPPETS: {
|
||||
GET: 'QUERY_GET_SNIPPETS',
|
||||
},
|
||||
};
|
||||
|
||||
export default QUERIES;
|
||||
|
Loading…
Reference in New Issue
Block a user