I'm trying to provide a basic autocompletion for something like this:
db.collection("Items").where("name", "==", "temp").limit(1).get();
Here's the code I have so far, using StreamLanguage of CodeMirror 6:
import {
IndentContext,
LanguageSupport,
StreamLanguage,
StringStream
} from "#codemirror/language";
import { tags as t } from "#lezer/highlight";
export const FireStoreLanguage = StreamLanguage.define({
name: "firestore",
startState: (indentUnit: number) => {
return {};
},
token: (stream: StringStream, state: any = {}): string | null => {
console.log(stream);
if (stream.match("db")) {
state.db = true;
return "keyword";
}
if (stream.match(".")) {
if (state.db) {
state.db = false;
state.collection = true;
return "keyword";
} else if (state.collection) {
state.collection = false;
state.where = true;
return "keyword";
} else if (state.where) {
state.where = false;
state.limit = true;
return "keyword";
} else if (state.limit) {
state.limit = false;
return "keyword";
}
}
if (stream.match("collection")) {
if (state.db) {
state.collection = true;
return "keyword";
}
}
if (stream.match("where")) {
if (state.collection) {
state.where = true;
return "keyword";
}
}
if (stream.match("limit")) {
if (state.where) {
state.limit = true;
return "keyword";
}
}
if (stream.match("get")) {
if (state.limit) {
state.limit = false;
return "keyword";
}
}
if (stream.match(/"(?:[^\\"]|\\.)*"/)) {
if (state.collection) {
return "string";
}
if (state.where) {
state.where = false;
state.whereValue = true;
return "string";
}
if (state.whereValue) {
state.whereValue = false;
return "string";
}
if (stream.match("==")) {
if (state.whereValue) {
state.whereValue = false;
state.whereOperator = true;
return "operator";
}
}
if (stream.match(/[0-9]+/)) {
if (state.limit) {
return "number";
}
}
}
stream.next();
return null;
},
blankLine: (state: {}, indentUnit: number): void => {},
copyState: (state: {}) => {},
indent: (
state: {},
textAfter: string,
context: IndentContext
): number | null => {
return 1;
},
languageData: {
commentTokens: { line: ";" },
},
tokenTable: {
db: t.keyword,
dot: t.punctuation,
collection: t.keyword,
get: t.keyword,
lParen: t.punctuation,
rParen: t.punctuation,
string: t.string,
},
});
export function firestore() {
return new LanguageSupport(FireStoreLanguage);
}
In React, here's how I use it(after building it):
import CodeMirror from "#uiw/react-codemirror";
import React from "react";
import { firestore } from "./firestore";
function App() {
const onChange = React.useCallback((value, viewUpdate) => {
console.log("value:", value);
}, []);
return (
<CodeMirror
value={``}
height="100vh"
extensions={[firestore()]}
onChange={onChange}
/>
);
}
export default App;
The editor loads okay, but no autocompletion is provided while I type!
What am I doing wrong or missing in the code above?
I was missing these parts:
export const FireStoreCompletion = FireStoreLanguage.data.of({
autocomplete: completeFromList([
{ label: "db", type: "namespace" },
{ label: "collection", type: "function" },
{ label: "where", type: "function" },
{ label: "limit", type: "function" },
{ label: "get", type: "function" },
]),
});
export function firestore() {
return new LanguageSupport(FireStoreLanguage, [FireStoreCompletion]);
}
Related
So, I have looked through the docs and answers on here and I'm still needing some help:
index.tsx
const getInfiniteArticles = ({ pageParams = 0 }) => {
const res = await axios.get('/api/articles', { params: { page: pageParams } });
return res.data;
}
api/articles.ts
const getArticles = async (req: NextApiRequest, res: NextApiResponse) => {
try {
const { page } = req.query;
const pageNum = Number(page);
const data = await NewsService.getArticles(getRange(pageNum));
return res.status(200).json({
data,
previousPage: pageNum > 0 ? (pageNum - 1) : null,
nextPage: pageNum + 1,
});
} catch (err) {
res.json(err);
res.status(405).end();
}
};
export default getArticles;
index.tsx
const { data: articlePages, fetchNextPage } = useInfiniteQuery(
'infinite-articles',
getInfiniteArticles,
{
getNextPageParam: (lastPage, allGroups) => {
console.log('lastPage: ', lastPage);
console.log('allGroups: ', allGroups);
return lastPage.nextPage;
}
});
const handleLoadMore = () => {
fetchNextPage();
};
console after clicking next page:
lastPage: { data: Array(50), previousPage: null, nextPage: 1}
allGroups: [
{ data: Array(50), previousPage: null, nextPage: 1},
{ data: Array(50), previousPage: null, nextPage: 1},
]
Any help on why I'm getting the same groups is appreciated! :)
So, it turns out my structure wasn't correct
const {
fetchNextPage,
fetchPreviousPage,
hasNextPage,
hasPreviousPage,
isFetchingNextPage,
isFetchingPreviousPage,
...result
} = useInfiniteQuery(queryKey, ({ pageParam = 1 }) => fetchPage(pageParam), {
...options,
getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,
getPreviousPageParam: (firstPage, allPages) => firstPage.prevCursor,
})
queryFn: (context: QueryFunctionContext) => Promise<TData>
The queryFn is supposed to be a synchronous function that returns a Promise
I was either passing an async function or I was returning the TData not a promise.
updated and working:
const getInfiniteArticles = ({ pageParam = 0 }) => axios.get('/api/articles', { params: { page: pageParam } });
const { data: articlePages, fetchNextPage } = useInfiniteQuery('articles', getInfiniteArticles, {
getNextPageParam: (lastPage, pages) => {
// the returned axios response
return lastPage.data.nextPage;
}
});
Reference Page
I can't use #computed. If I run my code bellow I get an error:
Uncaught TypeError: An element descriptor's .kind property must be either "method" or "field", but a decorator created an element descriptor with .kind "undefined"
at _toElementDescriptor (app.js:46281)
at _toElementFinisherExtras (app.js:46283)
at _decorateElement (app.js:46273)
at app.js:46269
at Array.forEach (<anonymous>)
at _decorateClass (app.js:46269)
at _decorate (app.js:46251)
at Module../src/App/stores/UserStore.js (app.js:46301)
at __webpack_require__ (bootstrap:19)
at Module../src/App/stores/index.js (index.js:1)
And here is my UserStore.js file:
import {
configure,
runInAction,
observable,
action,
computed
} from 'mobx'
import API from '../api'
configure({ enforceActions: 'observed' })
class UserStore {
#observable users
#observable state
#observable currPage
#observable hasMore
#observable errors
constructor() {
this.users = []
this.state = 'loading'
this.currPage = 0
this.hasMore = true
this.errors = []
}
#action
addUser = (user) => {
this.users.shift(user)
}
#action
addUsers = (users) => {
this.users = this.users.concat(users)
}
#action
async fetchUsers () {
let req;
try {
req = await API.allUsers()
runInAction(() => {
this.state = 'done'
this.addUsers(req.body.users || [])
this.hasMore = (req.body.users && req.body.users.length) ? true : false
this.currPage = this.currPage + 1
})
} catch (e) {
runInAction(() => {
this.state = 'error'
this.hasMore = false
})
}
}
#computed
get females () {
return this.users.filter(user => user.gender === 'female')
}
#computed
get males () {
return this.users.filters(user => user.gender === 'male')
}
}
const store = new UserStore();
export default store;
If I remove #computed the application loads.
The reason for my error was incorrect .babelrc configuration with Babel 7.
Failing
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"plugins": [
[ "#babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true } ],
"transform-class-properties",
"#babel/plugin-transform-runtime"
]
}
Working
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"plugins": [
[ "#babel/plugin-proposal-decorators", { "legacy": true } ],
[ "#babel/plugin-proposal-class-properties", {
"loose": true
}],
"#babel/plugin-transform-runtime"
]
}
I am new to ionic development and I am facing some issue
We are consuming an API in the ionic3 app.
When the user enters the credentials for login whether they are valid or invalid it shows the message according to the results from API in android.
But When i enter the wrong credentials in the ios build it will continue shows the loader and not giving the API result.
Following the app.component
import { Component, ViewChild } from '#angular/core';
import { Platform, Events, Nav, AlertController } from 'ionic-angular';
//import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { MenuController } from 'ionic-angular/components/app/menu-controller';
import { StorageService } from '../pages/shared/storage.service';
import { ToastService } from '../pages/shared/toast.service';
import { Network } from '#ionic-native/network';
//import { Observable } from 'rxjs/Observable';
import { UserService } from '../pages/shared/user.service';
import { Push, PushObject, PushOptions } from '#ionic-native/push';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild(Nav) nav;
alert: any;
isAlertShown: boolean;
task: any;
rootPage: any = '';
userDetails: any;
showSubmenu: boolean = true; //for open always
constructor(public platform: Platform, public splashScreen: SplashScreen,
public menu: MenuController,
private storage: StorageService, private toast: ToastService, public events: Events,
private push: Push,
private alertCtrl: AlertController, public network: Network, private api: UserService) {
platform.ready().then(() => {
this.userDetails = this.storage.getData('userDetails');
this.isAlertShown = false;
this.task = setInterval(() => {
this.checkInternet();
}, 3000);
this.pushSetup();
if (this.userDetails != undefined || this.userDetails != null) {
this.rootPage = 'welcome';
} else {
this.rootPage = 'login';
}
this.initializeApp();
});
events.subscribe('user:login', (username) => {
// user and time are the same arguments passed in `events.publish(user, time)`
this.getLoggedIn();
});
events.subscribe('user:logout', () => {
this.rootPage = 'login';
});
events.subscribe('root:change', (page) => {
// user and time are the same arguments passed in `events.publish(user, time)`
this.rootPage = page;
});
events.subscribe('user:pic', (userpic) => {
// user and time are the same arguments passed in `events.publish(user, time)`
this.userDetails = this.storage.getData('userDetails');
this.userDetails = {
userId: this.userDetails.userId,
username: this.userDetails.username,
profileUrl: userpic
}
this.storage.saveData('userDetails', this.userDetails);
this.getLoggedPic('pic');
});
}
initializeApp() { //for reduce time of white screen after splash
this.platform.ready().then(() => {
// do whatever you need to do here.
setTimeout(() => {
this.splashScreen.hide();
}, 100);
});
}
checkInternet() {
this.alert = this.alertCtrl.create({
title: 'Disconnected',
message: 'Please connect your device to internet',
buttons: [
{
text: 'Try again',
handler: () => {
this.checkagain();
}
}
], enableBackdropDismiss: false
});
this.api.getCategoryList()
.then(result => {
// console.clear();
if (result.type == 'error') {
if (this.isAlertShown == false) {
this.alert.present();
this.isAlertShown = true;
}
this.storage.saveData('connect', 'offline');
}
else if (result.status == true) {
this.storage.saveData('connect', 'online');
this.alert.dismiss();
}
})
}
public checkagain() {
this.isAlertShown = false;
//this.alert.dismiss();
}
public logout(): void {
this.storage.removeData('userDetails');
this.toast.ShowNotification('Logout Successful', 'bottom');
this.rootPage = 'login';
}
getLoggedPic(page) {
this.userDetails = this.storage.getData('userDetails');
if (page == "pic") {
this.userDetails.profileUrl = this.userDetails.profileUrl + "?" + new Date().getTime();
}
}
getLoggedIn() {
this.userDetails = this.storage.getData('userDetails');
if (this.userDetails != undefined || this.userDetails != null) {
this.rootPage = 'welcome';
this.userDetails = this.storage.getData('userDetails');
this.userDetails.profileUrl = this.userDetails.profileUrl + "?" + new Date().getTime();
} else {
this.rootPage = 'login';
}
}
openMenu(): void {
//Commented for click on edit profile to not collepes
//this.showSubmenu = !this.showSubmenu;
}
openPage(pagename: string) {
this.rootPage = pagename;
//this.nav.push(pagename);
}
openHomePage(pagename: string) {
this.rootPage = pagename;
}
pushSetup() {
console.log("inside pushSetup");
const options: PushOptions = {
android: {
senderID: 'xxxxxxxxxxx
forceShow: 'true'
},
ios: {
alert: 'true',
badge: true,
sound: 'false'
}
};
const pushObject: PushObject = this.push.init(options);
pushObject.on('notification').subscribe((notification: any) => console.log('Received a notification', notification));
pushObject.on('registration').subscribe((registration: any) => this.storage.saveData("token", registration.registrationId));
pushObject.on('error').subscribe(error => console.error('Error with Push plugin', error));
}
}
Following is my login.ts
import { Component } from '#angular/core';
import { IonicPage, NavController, Events, LoadingController } from 'ionic-angular';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { UserLogin } from '../shared/user';
import { UserService } from '../shared/user.service';
import { ToastService } from '../shared/toast.service';
import { StorageService } from '../shared/storage.service';
import { MenuController } from 'ionic-angular/components/app/menu-controller';
import { Platform } from 'ionic-angular';
#IonicPage({
name: 'login'
})
#Component({
selector: 'page-login',
templateUrl: 'login.html',
})
export class LoginPage {
public loginForm: FormGroup;
public submitted: boolean = false;
public userDetails: any;
private isUserLoggin: boolean = false;
private devicetype: any;
unamePattern = "(?:\d{10}|\w+#\w+\.\w{2,3})";
constructor(public nav: NavController, public formBuilder: FormBuilder,public platform: Platform,
private userService: UserService, private toast: ToastService, public loading: LoadingController, private storage: StorageService, private menuCtrl: MenuController,
public events: Events) {
if (this.platform.is('ios')) {
this.devicetype = "ios";
}
else {
this.devicetype = "android";
}
this.menuCtrl.enable(false); // for sidemenu disable
this.nav = nav;
this.isUserLoggin = this.userService.isUserLoggedIn();
this.loginForm = formBuilder.group({
username: ['', Validators.compose([Validators.required])],
password: ['', Validators.compose([Validators.required])]
});
}
// get username() {
// return this.loginForm.get('username');
// }
public save(model: UserLogin, isValid: boolean) {
this.submitted = true;
if (isValid) {
const formData = new FormData();
debugger
formData.append("user_login", model.username);
formData.append("user_password", model.password);
formData.append("device_type",this.devicetype);
formData.append("device_id",""+this.storage.getData("token"));
// console.log("storage id of device ="+this.storage.getData("token"));
let loader = this.loading.create({
content: 'Please wait'
});
loader.present().then(() => {
});
//this.toast.ShowLoaderOnLoad();
try {
this.userService.loginUser(formData)
.then(result => {
loader.dismiss();
if (result.status === true) {
this.userDetails = {
userId: result.data.user_id,
username: result.data.first_name,
profileUrl: result.data.picture_url
}
this.storage.saveData('userDetails', this.userDetails);
this.events.publish('user:login', result.data.first_name); //send an event to menu for show name
this.toast.ShowNotification(result.message, 'bottom');
this.nav.setRoot('welcome');
}
else if (result.status === false) {
this.loginForm = this.formBuilder.group({
username: [model.username, Validators.compose([Validators.required])],
password: ['', Validators.compose([Validators.required])]
});
this.submitted = false;
this.toast.ShowNotification(result.message, 'bottom');
}
else {
this.toast.ShowNotification('Something went wrong!', 'bottom');
this.loginForm.reset();
this.submitted = false;
isValid = false;
}
})
}
catch (error) {
this.loginForm = this.formBuilder.group({
username: [model.username, Validators.compose([Validators.required])],
password: ['', Validators.compose([Validators.required])]
});
this.submitted = false;
this.toast.ShowNotification('Something went wrong!', 'bottom');
}
}
}
ionViewWillEnter() {
if (this.isUserLoggin) {
this.nav.setRoot('welcome');
}
}
public gotoregister() {
this.nav.setRoot('register');
}
public gotoforget() {
this.nav.setRoot('forget');
}
public resetForm() {
this.submitted = false;
}
}
your
loader.present().then(() => {
});
is empty. Which means that your loader.dismiss() might activate before it is instantiated.
Try to put your try block in the call back of the present() function:
try {
etc...}
please Try with this
this.userService.loginUser(formData)
.then((res:any)=>{
//Success Code here
//Stop Loader
}).catch((err:any)=>{
//Error handling and Stop loader
})
I try to create my custom field.
so i do this :
import Vue from 'vue';
import Datepicker from 'vuejs-datepicker';
import VueFormGenerator from 'vue-form-generator';
Vue.component('fieldDatePicker', {
template: '<datepicker :placeholder="schema.placeholder" v-model="datePicker_model"></datepicker>',
components: {
Datepicker,
},
data: function() {
return {
datePicker_model: '',
};
},
mixins: [VueFormGenerator.abstractField],
mounted() {
this.datePicker_model = this.schema.default;
},
computed: {
value: {
get: function() {
return this.$moment(this.datePicker_model).format('DD-MM-YY')
},
set: function(newValue) {
throw 'TODO : ' + newValue;
// TODO converte and set value ! this.datePucker_model = newValue;
},
},
},
});
But my component didn't update the model of VueFormGenerator ...
What i forget ???
i add this to my component and it work ;)
watch: {
datePicker_model: function(newValue, OldValue) {
if(this.format(newValue) !== this.format(OldValue)) {
this.setModelValueByPath(this.schema.model, this.format(newValue));
}
},
},
When i use alertCtrl like this data is going to db it's working well.
addTodo(){
let prompt = this.alertCtrl.create({
title: 'add',
message: 'add',
inputs: [
{
name: 'title'
},
{
name: 'kan'
},
{
name: 'geos'
},
{
name: 'geod'
},
{
name: 'sahip'
}
],
buttons: [
{
text: 'İptal'
},
{
text: 'Kaydet',
handler: todo => {
if(todo){
this.showLoader();
this.todoService.createTodo(todo).then((result) => {
this.loading.dismiss();
this.todos = result;
console.log("todo created");
}, (err) => {
this.loading.dismiss();
console.log("not allowed");
});
}
}
}
]
});
prompt.present();
}
But when i try to use modal , showloader is running but createtodo is not working , no data is going to db .
addTodo(){
let modal = this.modalCtrl.create(KaneklePage);
modal.onDidDismiss(todo => {
if(todo){
this.showLoader();
this.todoService.createTodo(todo).then((result) => {
this.loading.dismiss();
this.todos = result;
console.log("todo created");
}, (err) => {
this.loading.dismiss();
console.log("not allowed");
});
}
});
modal.present();
}
This is dismiss code in modalpage
save(): void {
let todo = {
title: this.title,
kan: this.kan,
geos: this.geos,
geod: this.geod,
sahip: this.sahip
};
this.viewCtrl.dismiss(todo);
}