Skip to content

Commit

Permalink
Merge pull request #146 from evandor/TAB-485-gitsync-account
Browse files Browse the repository at this point in the history
Tab 485 gitsync account
  • Loading branch information
evandor authored Feb 11, 2024
2 parents 133edab + 676aa2c commit e4bb467
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 124 deletions.
7 changes: 4 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {StaticSuggestionIdent, Suggestion} from "src/models/Suggestion";
import {useRoute, useRouter} from "vue-router";
import {collection, doc, getDoc, getDocs} from "firebase/firestore";
import {firestore} from "boot/firebase";
import {Account} from "src/models/Account";
import {Account, UserData} from "src/models/Account";
const $q = useQuasar()
const router = useRouter()
Expand All @@ -33,10 +33,11 @@ onAuthStateChanged(auth, async (user) => {
// https://firebase.google.com/docs/reference/js/auth.user
console.log("%conAuthStateChanged: about to log in", "border:1px solid green")
// --- if we do this in useAuthStore.setUser(), we cannot properly run vitest any more
// --- if we do this in useAuthStore.setUser(), we cannot properly run vitest anymore (!?!)
const userDoc = await getDoc(doc(firestore, "users", user.uid))
const userData = userDoc.data()
const userData = userDoc.data() as UserData
const account = new Account(user.uid, userData)
console.log("created account object", account)
const querySnapshot = await getDocs(collection(firestore, "users", user.uid, "subscriptions"))
const products = new Set<string>()
querySnapshot.forEach((doc) => {
Expand Down
2 changes: 0 additions & 2 deletions src/boot/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const SYNC_TYPE = "sync.type"
const SYNC_GITLAB_URL = "sync.gitlab.url"
const SYNC_GITLAB_TOKEN = "sync.gitlab.token"

const SYNC_GITHUB_URL = "sync.github.url"
const SYNC_GITHUB_TOKEN = "sync.github.token"

const SYNC_COUCHDB_USERNAME = "sync.couchdb.username"
Expand Down Expand Up @@ -67,7 +66,6 @@ export {
SYNC_TYPE,
SYNC_GITLAB_URL,
SYNC_GITLAB_TOKEN,
SYNC_GITHUB_URL,
SYNC_GITHUB_TOKEN,
SYNC_COUCHDB_USERNAME,
SYNC_COUCHDB_PASSWORD,
Expand Down
19 changes: 17 additions & 2 deletions src/models/Account.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import {SyncType} from "stores/appStore";

export class SyncSettings {

constructor(
public type: SyncType | undefined,
public url: string | undefined,
) {
}
}

export class UserData {
sync: SyncSettings | undefined
}

export class Account {
created: number

constructor(
public id: string,
public userData: object | undefined,
public products: string[] = [],
public userData: UserData | undefined,
public products: string[] = []
) {
this.created = new Date().getTime()
}
Expand Down
12 changes: 2 additions & 10 deletions src/pages/SettingsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ onMounted(() => {
let suggestionsCounter = 0
watchEffect(() => {
console.log("watching settingsStore.activeToggles...", settingsStore.activeToggles)
//console.log("watching settingsStore.activeToggles...", settingsStore.activeToggles)
devEnabled.value = settingsStore.isEnabled('dev')
ddgEnabled.value = settingsStore.isEnabled('noDDG')
ignoreExtensionsEnabled.value = settingsStore.isEnabled('extensionsAsTabs')
Expand Down Expand Up @@ -569,7 +569,7 @@ watch(() => pageCapturePermissionGranted.value, (newValue, oldValue) => {
})
watchEffect(() => {
console.log("***setting dark mode to ", typeof darkMode.value, darkMode.value)
//console.log("***setting dark mode to ", typeof darkMode.value, darkMode.value)
switch (darkMode.value) {
case "true":
$q.dark.set(true)
Expand Down Expand Up @@ -622,14 +622,6 @@ watchEffect(() => {
sendMsg('detail-level-perTabset-changed', {level: detailLevelPerTabset.value})
})
watchEffect(() => {
console.log("activeToggles watcheffect", devEnabled.value)
//settingsStore.setFeatureToggle("stats", statsEnabled.value)
//settingsStore.setFeatureToggle("dev", devEnabled.value)
// settingsStore.setFeatureToggle("noDDG", !ddgEnabled.value)
// settingsStore.setFeatureToggle("extensionsAsTabs", !ignoreExtensionsEnabled.value)
})
watchEffect(() => {
localStorage.set("layout", view.value)
})
Expand Down
37 changes: 11 additions & 26 deletions src/pages/SidePanelPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -278,16 +278,15 @@
<template v-slot:title v-else>
<div class="text-subtitle1">
{{ toolbarTitle(tabsets as Tabset[]) }}
<q-icon
v-if="LocalStorage.getItem(SYNC_TYPE) as SyncType === SyncType.GITHUB && useAuthStore().isAuthenticated()"
class="q-ml-none" name="sync" size="12px">
<q-tooltip class="tooltip-small">Tabsets synced via {{ LocalStorage.getItem(SYNC_GITHUB_URL) }}
</q-tooltip>
</q-icon>
<q-icon v-if="LocalStorage.getItem(SYNC_TYPE) as SyncType === SyncType.MANAGED_GIT"
class="q-ml-none" name="sync" size="12px">
<q-tooltip class="tooltip-small">Tabsets are being synced automatically</q-tooltip>
</q-icon>
<!-- <q-icon-->
<!-- v-if="LocalStorage.getItem(SYNC_TYPE) as SyncType === SyncType.GITHUB && useAuthStore().isAuthenticated()"-->
<!-- class="q-ml-none" name="sync" size="12px">-->
<!-- <q-tooltip class="tooltip-small">Tabsets synced via {{ syncSource() }}</q-tooltip>-->
<!-- </q-icon>-->
<!-- <q-icon v-if="LocalStorage.getItem(SYNC_TYPE) as SyncType === SyncType.MANAGED_GIT"-->
<!-- class="q-ml-none" name="sync" size="12px">-->
<!-- <q-tooltip class="tooltip-small">Tabsets are being synced automatically</q-tooltip>-->
<!-- </q-icon>-->
</div>
</template>

Expand All @@ -309,7 +308,7 @@ import {useRouter} from "vue-router";
import {useUtils} from "src/services/Utils";
import {LocalStorage, openURL, scroll, uid, useQuasar} from "quasar";
import {useTabsetService} from "src/services/TabsetService2";
import {ListDetailLevel, useUiStore} from "src/stores/uiStore";
import {useUiStore} from "src/stores/uiStore";
import {usePermissionsStore} from "src/stores/permissionsStore";
import {useSpacesStore} from "src/stores/spacesStore";
import FirstToolbarHelper from "pages/sidepanel/helper/FirstToolbarHelper.vue";
Expand All @@ -330,12 +329,11 @@ import {CopyToClipboardCommand} from "src/domain/commands/CopyToClipboard";
import SidePanelTabsetDescriptionPage from "pages/sidepanel/SidePanelTabsetDescriptionPage.vue";
import ShareTabsetPubliclyDialog from "components/dialogues/ShareTabsetPubliclyDialog.vue";
import MqttService from "src/services/mqtt/MqttService";
import {SyncType, useAppStore} from "stores/appStore";
import {useVOnboarding, VOnboardingStep, VOnboardingWrapper} from 'v-onboarding'
import {FirebaseCall} from "src/services/firebase/FirebaseCall";
import getScrollTarget = scroll.getScrollTarget;
import InfoMessageWidget from "components/widgets/InfoMessageWidget.vue";
import {SYNC_GITHUB_URL, SYNC_TYPE, TITLE_IDENT} from "boot/constants";
import {SYNC_TYPE, TITLE_IDENT} from "boot/constants";
import AppService from "src/services/AppService";
import SidePanelToolbarButton from "components/buttons/SidePanelToolbarButton.vue";
Expand Down Expand Up @@ -903,19 +901,6 @@ const suggestTabsetImport = () => {
return false
}
const testShare = () => {
const shareData = {
title: "MDN",
text: "Learn web development on MDN!",
url: "https://developer.mozilla.org",
};
console.log(navigator)
if (navigator.canShare) {
console.log(navigator.canShare())
navigator.share(shareData).then((res) => console.log("res", res)).catch((err) => console.error(err))
}
}
const importSharedTabset = () => {
const currentTabUrl = useTabsStore().currentChromeTab?.url
if (currentTabUrl) {
Expand Down
59 changes: 27 additions & 32 deletions src/pages/helper/SyncingSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -303,30 +303,28 @@ import {
SYNC_COUCHDB_URL,
SYNC_COUCHDB_USERNAME,
SYNC_GITHUB_TOKEN,
SYNC_GITHUB_URL,
SYNC_GITLAB_TOKEN,
SYNC_GITLAB_URL,
SYNC_TYPE
} from "boot/constants";
import GitPersistentService from "src/services/persistence/GitPersistentService";
import {FirebaseCall} from "src/services/firebase/FirebaseCall";
import {Tabset, TabsetSharing} from "src/models/Tabset";
import {useTabsetService} from "src/services/TabsetService2";
import {useSuggestionsStore} from "stores/suggestionsStore";
import {StaticSuggestionIdent, Suggestion, SuggestionType} from "src/models/Suggestion";
import {useUtils} from "src/services/Utils";
import {useNotificationHandler} from "src/services/ErrorHandler";
import {ExecutionResult} from "src/domain/ExecutionResult";
import {useAuthStore} from "stores/authStore";
const {sendMsg} = useUtils()
const {handleSuccess, handleError} = useNotificationHandler()
const emits = defineEmits(['wasClicked'])
const syncType = ref<string | undefined>(undefined)
const tempSyncOption = ref<SyncType>(LocalStorage.getItem(SYNC_TYPE) as SyncType || SyncType.NONE)
const tempSyncOption = ref<SyncType>(useAuthStore().getAccount()?.userData?.sync?.type || SyncType.NONE)
const gitlabRepoToken = ref<string>(LocalStorage.getItem(SYNC_GITLAB_TOKEN) as string || '')
const gitlabRepoUrl = ref<string>(LocalStorage.getItem(SYNC_GITLAB_URL) as string || '')
// const gitlabRepoToken = ref<string>(LocalStorage.getItem(SYNC_GITLAB_TOKEN) as string || '')
// const gitlabRepoUrl = ref<string>(LocalStorage.getItem(SYNC_GITLAB_URL) as string || '')
const githubRepoToken = ref<string>(LocalStorage.getItem(SYNC_GITHUB_TOKEN) as string || '')
const githubRepoUrl = ref<string>(LocalStorage.getItem(SYNC_GITHUB_URL) as string || '')
const githubRepoUrl = ref<string>(useAuthStore().getAccount()?.userData?.sync?.url || '')
const couchdbUsername = ref<string>(LocalStorage.getItem(SYNC_COUCHDB_USERNAME) as string || '')
const couchdbPassword = ref<string>(LocalStorage.getItem(SYNC_COUCHDB_PASSWORD) as string || '')
Expand All @@ -353,9 +351,9 @@ function checkAndUpdate(val: string, ident: string) {
testResult.value = undefined
}
watchEffect(() => {
checkAndUpdate(githubRepoUrl.value, SYNC_GITHUB_URL)
})
// watchEffect(() => {
// checkAndUpdate(githubRepoUrl.value, SYNC_GITHUB_URL)
// })
watchEffect(() => {
checkAndUpdate(githubRepoToken.value, SYNC_GITHUB_TOKEN)
Expand All @@ -367,9 +365,9 @@ watchEffect(() => {
checkAndUpdate(couchdbUrl.value, SYNC_COUCHDB_URL)
})
watchEffect(() => {
syncType.value = LocalStorage.getItem(SYNC_TYPE) as SyncType
})
// watchEffect(() => {
// syncType.value = LocalStorage.getItem(SYNC_TYPE) as SyncType
// })
const testGitConnection = async () => {
Expand Down Expand Up @@ -402,9 +400,18 @@ const testDbConnection = async () => {
}
}
const startGitSyncing = () => {
LocalStorage.set(SYNC_TYPE, tempSyncOption.value)
sendMsg('reload-application')
const startGitSyncing = async () => {
try {
const res = await FirebaseCall.patch("/users/" + useAuthStore().user.uid,
{sync: {type:tempSyncOption.value, url:githubRepoUrl.value}})
console.log("res", res)
LocalStorage.set(SYNC_TYPE, tempSyncOption.value)
sendMsg('reload-application')
handleSuccess(new ExecutionResult<string>("done", "done"))
} catch (err) {
console.error("startGitSyncing Error", err)
handleError('could not start syncing')
}
//useSuggestionsStore().addSuggestion(Suggestion.getStaticSuggestion(StaticSuggestionIdent.RESTART_SUGGESTED))
}
const stopGitSyncing = () => {
Expand All @@ -418,18 +425,6 @@ const startSyncMessage = (targetType: SyncType) => testResult.value === 'success
const stopSyncMessage = () => (syncType.value !== tempSyncOption.value) && syncType.value === SyncType.GITHUB && tempSyncOption.value === SyncType.NONE
// const testSubscription = () => {
// console.log("testing subscription", subscription.value)
// FirebaseCall.get("/share/public/" + tabsetId + "?cb=" + new Date().getTime(), false)
// .then((res: any) => {
// const newTabset = res as Tabset
// newTabset.sharing = TabsetSharing.UNSHARED
// //_.forEach(newTabset.tabs, t => t.preview = TabPreview.THUMBNAIL)
// useTabsetService().saveTabset(newTabset)
// useTabsetService().reloadTabset(newTabset.id)
// })
// }
const checkManagedGitSetup = async () => {
try {
const response = await FirebaseCall.post("/subscriptions", {"userId": "abc"})
Expand Down
5 changes: 2 additions & 3 deletions src/services/AppService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {FeatureIdent} from "src/models/AppFeature";
import {useMessagesStore} from "src/stores/messagesStore";
import {SyncType, useAppStore} from "stores/appStore";
import GitPersistentService from "src/services/persistence/GitPersistentService";
import {SYNC_GITHUB_URL, SYNC_TYPE} from "boot/constants";
import {useAuthStore} from "stores/authStore";
import PersistenceService from "src/services/PersistenceService";
import {useUiStore} from "stores/uiStore";
Expand Down Expand Up @@ -99,8 +98,8 @@ class AppService {

if (useAuthStore().isAuthenticated()) {
// sync features
const syncType = LocalStorage.getItem(SYNC_TYPE) as SyncType || SyncType.NONE
const syncUrl = LocalStorage.getItem(SYNC_GITHUB_URL) as string
const syncType = useAuthStore().getAccount()?.userData?.sync?.type || SyncType.NONE
const syncUrl = useAuthStore().getAccount()?.userData?.sync?.url
const dbOrGitDb = useGitStore(syncType, syncUrl) ?
useDB(undefined).gitDb :
useDB(undefined).db
Expand Down
80 changes: 51 additions & 29 deletions src/services/firebase/FirebaseCall.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {api} from "boot/axios";
import axios, {AxiosError} from 'axios';
import { useAuthStore } from "src/stores/authStore";
import {useAuthStore} from "src/stores/authStore";

export abstract class FirebaseCall<T> {

Expand All @@ -21,41 +21,63 @@ export abstract class FirebaseCall<T> {
}
}

static async delete<T>(path: string): Promise<T> {
try {
const token = await useAuthStore().getToken(api)
const response = await api.delete<T>(`${process.env.BACKEND_URL}${path}`, {headers: {'AuthToken': token}})
return response.data;
} catch (err) {
FirebaseCall.handleError(err)
return Promise.reject("user not authenticated")
}
}
// static async delete<T>(path: string): Promise<T> {
// try {
// useAuthStore().user.getIdToken()
// .then((idToken) => {
// const response = api.delete<T>(`${process.env.BACKEND_URL}${path}`, {headers: {'AuthToken': token}})
// return response.data;
// })
// } catch (err) {
// FirebaseCall.handleError(err)
// return Promise.reject("user not authenticated")
// }
// }

static post(path: string, data: object, resType = "json", fullPath = false) {
console.log("firebase call to ", path)
return useAuthStore().getToken(api).then((token: string) => {
const urlToUse = fullPath ? path : `${process.env.BACKEND_URL}${path}`
console.log("posting to", urlToUse )
// @ts-ignore
return api.post(urlToUse, data, {headers: {'AuthToken': token}, responseType: resType})
.catch((err: any) => {
FirebaseCall.handleError(err)
return Promise.reject(err)
})
})
useAuthStore().user.getIdToken()
.then((idToken) => {
//console.log("got idTOken", idToken)
const urlToUse = fullPath ? path : `${process.env.BACKEND_URL}${path}`
console.log("posting to", urlToUse)
// @ts-ignore
return api.post(urlToUse, data, {headers: {'AuthToken': idToken}, responseType: resType})
.catch((err: any) => {
FirebaseCall.handleError(err)
return Promise.reject(err)
})
})
}

static put(path: string, data: object) {
return useAuthStore().getToken(api).then((token: string) => {
return api.put(`${process.env.BACKEND_URL}${path}`, data, {headers: {'AuthToken': token}})
.catch((err: any) => {
FirebaseCall.handleError(err)
return Promise.reject("user not authenticated")
})
})

static patch(path: string, data: object, resType = "json", fullPath = false) {
console.log("firebase call to ", path)
// TODO use approach as in onAuthStateChanged?
useAuthStore().user.getIdToken()
.then((idToken) => {
//console.log("got idTOken", idToken)
const urlToUse = fullPath ? path : `${process.env.BACKEND_URL}${path}`
console.log("posting to", urlToUse)
// @ts-ignore
return api.patch(urlToUse, data, {headers: {'AuthToken': idToken}, responseType: resType})
.catch((err: any) => {
FirebaseCall.handleError(err)
return Promise.reject(err)
})
})
}

// static put(path: string, data: object) {
// return useAuthStore().getToken(api).then((token: string) => {
// return api.put(`${process.env.BACKEND_URL}${path}`, data, {headers: {'AuthToken': token}})
// .catch((err: any) => {
// FirebaseCall.handleError(err)
// return Promise.reject("user not authenticated")
// })
// })
// }

private static handleError(err: any) {
if (axios.isAxiosError(err)) {
const axiosError = err as AxiosError
Expand Down
Loading

0 comments on commit e4bb467

Please sign in to comment.