diff --git a/CHANGELOG.md b/CHANGELOG.md index ad436e37..711a8ec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.9.0] - 2025-01-21 +- Removed button "View this repo on the Web" from PopUps and Side Panel + +## [4.8.0] - 2025-01-17 +- Adding repository to Org/Team during "Connect Repository" + +## [4.7.0] - 2025-01-08 +- Resetting user session upon Logout + ## [4.6.0] - 2024-12-25 - Switching off daily-activity-alert since we now have Slack Alerts enabled diff --git a/package.json b/package.json index d00108f3..2dfc7eb3 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "CodeSync", "description": "CodeSync's AI-generated summaries provide clear, insightful coding overviews directly in your IDE, keeping your team aligned without manual tracking. Seamlessly integrate with GitHub and Slack to streamline your workflow.", "icon": "images/icon.png", - "version": "4.6.0", + "version": "4.9.0", "publisher": "codesync", "engines": { "vscode": "^1.86.0", @@ -172,23 +172,23 @@ }, { "view": "codesync-repo-connected", - "contents": "Repo is in sync with CodeSync.\n[View this repo on the web](command:codesync.trackRepo)\n[View Dashboard](command:codesync.viewDashboard)\n[Disconnect repo](command:codesync.disconnectRepo)\n[Logout](command:codesync.logout)" + "contents": "Repo is in sync with CodeSync.\n[View Dashboard](command:codesync.viewDashboard)\n[Disconnect repo](command:codesync.disconnectRepo)\n[Logout](command:codesync.logout)" }, { "view": "codesync-upgrade-to-pro-plan", - "contents": "Repo is in sync with CodeSync.\n[View this repo on the web](command:codesync.trackRepo)\n[Upgrade plan](command:codesync.upgradePlan)\n[View Dashboard](command:codesync.viewDashboard)\n[Disconnect repo](command:codesync.disconnectRepo)\n[Logout](command:codesync.logout)" + "contents": "Repo is in sync with CodeSync.\n[Upgrade plan](command:codesync.upgradePlan)\n[View Dashboard](command:codesync.viewDashboard)\n[Disconnect repo](command:codesync.disconnectRepo)\n[Logout](command:codesync.logout)" }, { "view": "codesync-try-pro-for-free", - "contents": "Repo is in sync with CodeSync.\n[View this repo on the web](command:codesync.trackRepo)\n[Upgrade plan for free](command:codesync.upgradePlan)\n[View Dashboard](command:codesync.viewDashboard)\n[Disconnect repo](command:codesync.disconnectRepo)\n[Logout](command:codesync.logout)" + "contents": "Repo is in sync with CodeSync.\n[Upgrade plan for free](command:codesync.upgradePlan)\n[View Dashboard](command:codesync.viewDashboard)\n[Disconnect repo](command:codesync.disconnectRepo)\n[Logout](command:codesync.logout)" }, { "view": "codesync-opened-repo-is-sub-dir-of-connected-repo", - "contents": "You are good to go ✅.\nCurrent directory is in sync with CodeSync because a parent repo is in sync.\n[View parent repo on web](command:codesync.trackRepo)\n[Disconnect parent repo](command:codesync.disconnectRepo)\n[View Dashboard](command:codesync.viewDashboard)\n[Logout](command:codesync.logout)" + "contents": "You are good to go ✅.\nCurrent directory is in sync with CodeSync because a parent repo is in sync.\n[Disconnect parent repo](command:codesync.disconnectRepo)\n[View Dashboard](command:codesync.viewDashboard)\n[Logout](command:codesync.logout)" }, { "view": "codesync-sub-dir-is-syncignored", - "contents": "Current directory is syncignored by a parent repo. To sync this directory, remove it from .syncignore.\n[Open .syncignore](command:codesync.openSyncIgnore)\n[View parent repo on web](command:codesync.trackRepo)\n[Disconnect parent repo](command:codesync.disconnectRepo)\n[View Dashboard](command:codesync.viewDashboard)\n[Logout](command:codesync.logout)" + "contents": "Current directory is syncignored by a parent repo. To sync this directory, remove it from .syncignore.\n[Open .syncignore](command:codesync.openSyncIgnore)\n[Disconnect parent repo](command:codesync.disconnectRepo)\n[View Dashboard](command:codesync.viewDashboard)\n[Logout](command:codesync.logout)" }, { "view": "codesync-is-loading", diff --git a/src/codesyncd/handlers/diff_handler.ts b/src/codesyncd/handlers/diff_handler.ts index dd69064e..38e4c1e0 100644 --- a/src/codesyncd/handlers/diff_handler.ts +++ b/src/codesyncd/handlers/diff_handler.ts @@ -8,7 +8,7 @@ import {generateSettings} from "../../settings"; import {readYML} from "../../utils/common"; import {CodeSyncLogger} from "../../logger"; import {pathUtils} from "../../utils/path_utils"; -import {initUtils} from "../../init/utils"; +import {initUtils} from "../../connect_repo/utils"; import {VSCODE} from "../../constants"; import { removeFile } from "../../utils/file_utils"; diff --git a/src/codesyncd/populate_buffer.ts b/src/codesyncd/populate_buffer.ts index e2776db3..b2be1d61 100644 --- a/src/codesyncd/populate_buffer.ts +++ b/src/codesyncd/populate_buffer.ts @@ -5,9 +5,9 @@ import { glob } from 'glob'; import {isBinaryFileSync} from "isbinaryfile"; import stringSimilarity from "string-similarity"; -import {initUtils} from "../init/utils"; +import {initUtils} from "../connect_repo/utils"; import {IFileToUpload} from "../interface"; -import {initHandler} from "../init/init_handler"; +import {initHandler} from "../connect_repo/connect_repo_handler"; import {generateSettings} from "../settings"; import {pathUtils} from "../utils/path_utils"; import { @@ -36,7 +36,7 @@ import {eventHandler} from "../events/event_handler"; import { CodeSyncLogger } from "../logger"; import { CODESYNC_STATES, CodeSyncState } from "../utils/state_utils"; import { removeFile } from "../utils/file_utils"; -import { s3UploaderUtils } from "../init/s3_uploader"; +import { s3UploaderUtils } from "../connect_repo/s3_uploader"; import { UserState } from "../utils/user_utils"; diff --git a/src/init/init_handler.ts b/src/connect_repo/connect_repo_handler.ts similarity index 86% rename from src/init/init_handler.ts rename to src/connect_repo/connect_repo_handler.ts index 24d8adc3..dbf84e60 100644 --- a/src/init/init_handler.ts +++ b/src/connect_repo/connect_repo_handler.ts @@ -11,7 +11,7 @@ import { import { initUtils } from './utils'; import { IUser } from '../interface'; import { pathUtils } from "../utils/path_utils"; -import { askPublicPrivate } from '../utils/notifications'; +import { askPersonalOrOrgRepo, askPublicPrivate } from '../utils/notifications'; import { isAccountActive } from '../utils/auth_utils'; import { checkServerDown } from "../utils/api_utils"; import { getBranch, readFile } from "../utils/common"; @@ -76,25 +76,24 @@ export class initHandler { // Only ask for public/private in case of Repo Sync. Do not ask for Branch Sync. if (this.viaDaemon) { - return await this.postPublicPrivate(user.email, false); + return await this.postOrgSelection(user.email, false); } // Open .syncignore and ask public/private info const setting: vscode.Uri = vscode.Uri.parse("file:" + syncignorePath); // Opening .syncignore return await vscode.workspace.openTextDocument(setting).then(async (a: vscode.TextDocument) => { return await vscode.window.showTextDocument(a, 1, false).then(async e => { - const buttonSelected = await askPublicPrivate(this.repoPath); - if (!buttonSelected) { - vscode.window.showWarningMessage(NOTIFICATION.INIT_CANCELLED); + const json = await askPersonalOrOrgRepo(this.accessToken, this.repoPath); + if (json.isCancelled) { + vscode.window.showWarningMessage(NOTIFICATION.CONNECT_REPO_CANCELLED); return false; } - const isPublic = buttonSelected == NOTIFICATION.PUBLIC; - return await this.postPublicPrivate(user.email, isPublic); + return await this.postOrgSelection(user.email, false, json.orgId, json.teamId); }); }); }; - postPublicPrivate = async (userEmail: string, isPublic: boolean) => { + postOrgSelection = async (userEmail: string, isPublic = false, orgId = null, teamId = null) => { CodeSyncState.set(CODESYNC_STATES.IS_SYNCING_BRANCH, new Date().getTime()); const initUtilsObj = new initUtils(this.repoPath, this.viaDaemon); // get item paths to upload and copy in respective repos @@ -108,7 +107,9 @@ export class initHandler { const shadowRepoBranchPath = pathUtilsObj.getShadowRepoBranchPath(); initUtilsObj.copyFilesTo(filePaths, shadowRepoBranchPath); // Upload repo/branch - const uploaded = await initUtilsObj.uploadRepo(this.branch, this.accessToken, itemPaths, userEmail, isPublic); + const uploaded = await initUtilsObj.uploadRepo(this.branch, this.accessToken, + itemPaths, userEmail, isPublic, null, orgId, teamId + ); return uploaded; }; } diff --git a/src/init/s3_uploader.ts b/src/connect_repo/s3_uploader.ts similarity index 100% rename from src/init/s3_uploader.ts rename to src/connect_repo/s3_uploader.ts diff --git a/src/init/utils.ts b/src/connect_repo/utils.ts similarity index 95% rename from src/init/utils.ts rename to src/connect_repo/utils.ts index 0352762c..060fe138 100644 --- a/src/init/utils.ts +++ b/src/connect_repo/utils.ts @@ -16,7 +16,6 @@ import { CONNECTION_ERROR_MESSAGE, VSCODE, NOTIFICATION, BRANCH_SYNC_TIMEOUT, co import { getGlobIgnorePatterns, readYML, getSyncIgnoreItems, shouldIgnorePath, getDefaultIgnorePatterns } from '../utils/common'; import { CodeSyncState, CODESYNC_STATES } from '../utils/state_utils'; import { s3UploaderUtils } from './s3_uploader'; -import { trackRepoHandler } from '../handlers/commands_handler'; import gitCommitInfo from 'git-commit-info'; import { RepoPlanLimitsState, RepoState } from '../utils/repo_state_utils'; import { captureTabs } from '../utils/tab_utils'; @@ -143,19 +142,13 @@ export class initUtils { CodeSyncState.set(CODESYNC_STATES.IS_SYNCING_BRANCH, false); // Hide Connect Repo vscode.commands.executeCommand('setContext', contextVariables.showConnectRepoView, false); + if (this.viaDaemon) return; // Show success notification - if (!this.viaDaemon) { - vscode.window.showInformationMessage(NOTIFICATION.REPO_CONNECTED, ...[ - NOTIFICATION.TRACK_IT - ]).then(selection => { - if (!selection) return; - if (selection === NOTIFICATION.TRACK_IT) return trackRepoHandler(); - }); - } + vscode.window.showInformationMessage(NOTIFICATION.REPO_CONNECTED); } async uploadRepo(branch: string, token: string, itemPaths: IFileToUpload[], - userEmail: string, isPublic=false, repoId=null) { + userEmail: string, isPublic=false, repoId=null, orgId=null, teamId=null) { // Check plan limits const repoLimitsState = new RepoPlanLimitsState(this.repoPath).get(); if (repoLimitsState.planLimitReached && !repoLimitsState.canRetry) return false; @@ -176,7 +169,9 @@ export class initUtils { if (!repoState.IS_CONNECTED) { configJSON.repos[this.repoPath] = { branches: {}, - email: userEmail + email: userEmail, + orgId: orgId, + teamId: teamId }; configJSON.repos[this.repoPath].branches[branch] = branchFiles; fs.writeFileSync(this.settings.CONFIG_PATH, yaml.dump(configJSON)); @@ -212,7 +207,9 @@ export class initUtils { commit_hash, files_data: JSON.stringify(filesData), source: VSCODE, - platform: os.platform() + platform: os.platform(), + org_id: configJSON.repos[this.repoPath].orgId, + team_id: configJSON.repos[this.repoPath].teamId }; const json = await uploadRepoToServer(token, data, repoId); diff --git a/src/constants.ts b/src/constants.ts index 77b7f1dc..8959f073 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -31,6 +31,7 @@ export const apiRoutes = (): IApiRoutes => { REPO_INIT: generateApiUrl("/init"), REPOS: generateApiUrl(API_PATH.REPOS), USERS: generateApiUrl("/users"), + USER_ORGANIZATIONS: generateApiUrl("/orgs"), REACTIVATE_ACCOUNT: generateApiUrl("/users/reactivate"), USER_SUBSCRIPTION: generateApiUrl("/users/subscription"), DIFFS_WEBSOCKET: generateSocketUrl("/v2/websocket"), @@ -69,7 +70,8 @@ export const NOTIFICATION_BUTTON = { TRY_PRO_FOR_FREE: "Try Pro plan for free", TRY_TEAM_FOR_FREE: "Try Team plan for free", UPGRADE_TO_PRO: "Upgrade to Pro plan", - UPGRADE_TO_TEAM: "Upgrade to Team plan" + UPGRADE_TO_TEAM: "Upgrade to Team plan", + REPO_IS_PERSONAL: "Repo is personal" }; // Notification Messages @@ -107,7 +109,7 @@ export const NOTIFICATION = { UPGRADE_ORG_PLAN: "Please upgrade your Organization's plan to continue using CodeSync", UPGRADE_TO_PRO: "Upgrade to Pro plan", TRY_PRO_FOR_FREE: "Try Pro plan for free", - INIT_CANCELLED: "Init process was cancelled", + CONNECT_REPO_CANCELLED: "'Connect Repo' process was cancelled", NO_VALID_ACCOUNT: "No valid account found", WAITING_FOR_LOGIN_CONFIRMATION: "Waiting for login confirmation from CodeSync...", REPO_IN_SYNC: "is in sync with CodeSync.", @@ -125,7 +127,9 @@ export const NOTIFICATION = { SIGNUP_FAILED: "Sign up to CodeSync failed!", ACCOUNT_DEACTIVATED: "Your account has been deactivated. Please click 'Reactivate Account' below to resume syncing.", FREE_TIER_LIMIT_REACHED: "We hope you've found CodeSync useful. You'have hit the limit of Free tier for repo", - PRIVATE_REPO_COUNT_LIMIT_REACHED: "In the Free plan, you can have just one Private Repository" + PRIVATE_REPO_COUNT_LIMIT_REACHED: "In the Free plan, you can have just one Private Repository", + ASK_ORG_REPO: "Would you like to add this repository to any of the following organizations?", + ASK_TEAM_REPO: "Which team should this repository be added to?" }; export const getRepoInSyncMsg = (repoPath: string) => { diff --git a/src/events/event_handler.ts b/src/events/event_handler.ts index 6e490a61..4b906623 100644 --- a/src/events/event_handler.ts +++ b/src/events/event_handler.ts @@ -5,7 +5,7 @@ import vscode from 'vscode'; import { globSync } from 'glob'; import { IDiff } from "../interface"; -import { initUtils } from "../init/utils"; +import { initUtils } from "../connect_repo/utils"; import { formatDatetime, getBranch, getDefaultIgnorePatterns, getSyncIgnoreItems, readFile, readYML, shouldIgnorePath } from "../utils/common"; import { generateSettings } from "../settings"; import { pathUtils } from "../utils/path_utils"; diff --git a/src/interface.ts b/src/interface.ts index 1a6bebd9..457d5e16 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -149,6 +149,7 @@ export interface IApiRoutes { REPO_INIT: string; REPOS: string; USERS: string; + USER_ORGANIZATIONS: string; REACTIVATE_ACCOUNT: string; USER_SUBSCRIPTION: string; DIFFS_WEBSOCKET: string; diff --git a/src/server/server.ts b/src/server/server.ts index 3cf87464..b1aab3c0 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -58,7 +58,7 @@ export const initExpressServer = () => { const userState = new UserState(); const activeUser = userState.getUser(); if (activeUser && activeUser.email !== userResponse.email) return res.send(msgs.TOKEN_VERIFICATION_FAILED); - postSuccessLogout(); + await postSuccessLogout(); const redirectURL = generateWebUrl("", {type: "logout"}); // http://localhost:3000/?utm_medium=plugin&utm_source=vscode&type=logout res.redirect(redirectURL); diff --git a/src/settings.ts b/src/settings.ts index c3241b97..c9c2fb17 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -3,6 +3,7 @@ import untildify from "untildify"; import { prodConfig } from "./config/prod"; import { stagingConfig } from "./config/staging"; import { devConfig } from "./config/dev"; +import { formatDatetime } from "./utils/common"; // Set this to true for Development const DEBUG = false; @@ -70,8 +71,10 @@ export const generateSettings = () => { */ // System Directories for CodeSync const rootRepo = untildify(systemConfig.ROOT_REPO); + const backupRepo = untildify(`${systemConfig.ROOT_REPO}-${formatDatetime()}`); const systemDirectories = { CODESYNC_ROOT: rootRepo, + BACKUP_ROOT: backupRepo, DIFFS_REPO: path.join(rootRepo, ".diffs", ".vscode"), TABS_PATH: path.join(rootRepo, ".tabs", ".vscode"), ORIGINALS_REPO: path.join(rootRepo, ".originals"), diff --git a/src/utils/api_utils.ts b/src/utils/api_utils.ts index 2bc16473..15eded45 100644 --- a/src/utils/api_utils.ts +++ b/src/utils/api_utils.ts @@ -1,6 +1,7 @@ import fetch from "node-fetch"; import { apiRoutes } from "../constants"; +import { generateApiUrl } from "./url_utils"; export const checkServerDown = async () => { @@ -98,3 +99,55 @@ export const getUserSubcription = async (accessToken: string) => { error }; }; + + +export const getRepoAvailableOrganizations = async (accessToken: string, repoName: string) => { + let error = ""; + let orgs = []; + const url = `${apiRoutes().USER_ORGANIZATIONS}&repo_name=${repoName}`; + const response = await fetch(url, { + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Basic ${accessToken}` + } + }) + .then(res => res.json()) + .then(json => json) + .catch(err => error = err); + if (response.error) { + error = response.error.message; + } else { + orgs = response.orgs; + } + + return { + orgs, + error + }; +}; + +export const getOrgTeams = async (accessToken: string, orgId: number) => { + let error = ""; + let teams = []; + const orgTeamsUrl = generateApiUrl(`/orgs/${orgId}/teams`); + const response = await fetch( + orgTeamsUrl, { + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Basic ${accessToken}` + } + }) + .then(res => res.json()) + .then(json => json) + .catch(err => error = err); + if (response.error) { + error = response.error.message; + } else { + teams = response.teams; + } + + return { + teams, + error + }; +}; \ No newline at end of file diff --git a/src/utils/auth_utils.ts b/src/utils/auth_utils.ts index 78b50227..c75565ed 100644 --- a/src/utils/auth_utils.ts +++ b/src/utils/auth_utils.ts @@ -9,13 +9,13 @@ import {readYML} from './common'; import {showConnectRepo} from "./notifications"; import {createUserWithApi} from "./api_utils"; import {generateSettings} from "../settings"; -import {trackRepoHandler} from "../handlers/commands_handler"; import {contextVariables, ECONNREFUSED, getRepoInSyncMsg, HttpStatusCodes, NOTIFICATION, NOTIFICATION_BUTTON} from "../constants"; import { CodeSyncLogger } from "../logger"; import { pathUtils } from "./path_utils"; import { RepoState } from "./repo_state_utils"; import { UserState } from "./user_utils"; import { authHandler, reactivateAccountHandler } from "../handlers/user_commands"; +import { createSystemDirectories, setupCodeSync } from "./setup_utils"; export const isPortAvailable = async (port: number) => { @@ -63,14 +63,7 @@ export const postSuccessLogin = (userEmail: string, accessToken: string) => { return showConnectRepo(repoPath, userEmail, accessToken); } // Show notification that repo is in sync - vscode.window.showInformationMessage(getRepoInSyncMsg(repoPath), ...[ - NOTIFICATION.TRACK_IT - ]).then(selection => { - if (!selection) { return; } - if (selection === NOTIFICATION.TRACK_IT) { - trackRepoHandler(); - } - }); + vscode.window.showInformationMessage(getRepoInSyncMsg(repoPath)); }; const postDeactivatedAccount = (userEmail: string, accessToken: string) => { @@ -152,6 +145,19 @@ export const markUsersInactive = (notify=true) => { }; +export const resetUserSession = async () => { + const settings = generateSettings(); + try { + fs.renameSync(settings.CODESYNC_ROOT, settings.BACKUP_ROOT); + } catch (e) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + CodeSyncLogger.error("Failed to reset root repo", e.stack); + } + const repoPath = pathUtils.getRootPath(); + await setupCodeSync(repoPath); +}; + export const askAndTriggerSignUp = () => { // Trigger sign up process vscode.window.showErrorMessage( @@ -169,8 +175,10 @@ const parseJwt = (token: string) => { return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); }; -export const postSuccessLogout = () => { +export const postSuccessLogout = async () => { markUsersInactive(); + // Rename system directory + await resetUserSession(); if ((global as any).socketConnection) { (global as any).socketConnection.close(); (global as any).socketConnection = null; diff --git a/src/utils/notifications.ts b/src/utils/notifications.ts index c2c82bf0..3ca7d50c 100644 --- a/src/utils/notifications.ts +++ b/src/utils/notifications.ts @@ -1,11 +1,14 @@ +import path from 'path'; import vscode from 'vscode'; -import { initHandler } from '../init/init_handler'; +import { initHandler } from '../connect_repo/connect_repo_handler'; import { getPublicPrivateMsg, getDirectorySyncIgnoredMsg, NOTIFICATION, getConnectRepoMsgAfterJoin, getDisconnectedRepoMsg, NOTIFICATION_BUTTON, getUpgradePlanMsg, WebPaths} from '../constants'; -import { trackRepoHandler, openSyncIgnoreHandler, disconnectRepoHandler, reconnectRepoHandler } from '../handlers/commands_handler'; +import { openSyncIgnoreHandler, disconnectRepoHandler, reconnectRepoHandler } from '../handlers/commands_handler'; import { UserState } from './user_utils'; import { generateWebUrl } from './url_utils'; import { authHandler, requestDemoUrl } from '../handlers/user_commands'; import { getCanAwailTrial } from './pricing_utils'; +import { getOrgTeams, getRepoAvailableOrganizations } from './api_utils'; +import { CodeSyncLogger } from '../logger'; export const showSignUpButtons = () => { vscode.window.showInformationMessage( @@ -90,6 +93,7 @@ export const showChooseAccount = async (repoPath: string) => { // }); }; + export const askPublicPrivate = async (repoPath: string) => { const msg = getPublicPrivateMsg(repoPath); const buttonSelected = await vscode.window.showInformationMessage(msg, { modal: true }, ...[ @@ -99,17 +103,63 @@ export const askPublicPrivate = async (repoPath: string) => { return buttonSelected; }; + +export const askPersonalOrOrgRepo = async (accessToken: string, repoPath: string) => { + const repoName = path.basename(repoPath); + let orgId = null; + let teamId = null; + const respJson = { + orgId, + teamId, + isCancelled: false, + error: false + }; + const orgResponse = await getRepoAvailableOrganizations(accessToken, repoName); + if (orgResponse.error) { + CodeSyncLogger.error("Error getting user orgs from the API", orgResponse.error); + respJson.error = true; + return respJson; + } + if (orgResponse.orgs.length === 0) return respJson; + const orgNames = orgResponse.orgs.map((org: { name: string; }) => org.name); + const selectedOrg = await vscode.window.showInformationMessage( + NOTIFICATION.ASK_ORG_REPO, { modal: true }, NOTIFICATION_BUTTON.REPO_IS_PERSONAL, ...orgNames + ).then(selection => selection); + if (!selectedOrg) { + respJson.isCancelled = true; + return respJson; + } + if (selectedOrg === NOTIFICATION_BUTTON.REPO_IS_PERSONAL) return respJson; + orgId = orgResponse.orgs.filter((org: { name: string, id: number; }) => org.name === selectedOrg)[0].id; + respJson.orgId = orgId; + // Get the Org Teams + const teamResponse = await getOrgTeams(accessToken, orgId); + if (teamResponse.error) { + CodeSyncLogger.error("Error getting org teams from the API", teamResponse.error); + respJson.error = true; + return respJson; + } + if (teamResponse.teams.length === 0) return respJson; + const teamNames = teamResponse.teams.map((team: { name: string; }) => team.name); + const selectedTeam = await vscode.window.showInformationMessage( + NOTIFICATION.ASK_TEAM_REPO, { modal: true }, ...teamNames + ).then(selection => selection); + if (selectedTeam) { + teamId = teamResponse.teams.filter((team: { name: string, id: number; }) => team.name === selectedTeam)[0].id; + } + respJson.orgId = orgId; + respJson.teamId = teamId; + return respJson; +}; + + export const showSyncIgnoredRepo = (repoPath: string, parentRepoPath: string) => { const msg = getDirectorySyncIgnoredMsg(repoPath, parentRepoPath); vscode.window.showInformationMessage(msg, NOTIFICATION.OPEN_SYNCIGNORE, - NOTIFICATION.TRACK_PARENT_REPO, NOTIFICATION.DISCONNECT_PARENT_REPO).then(async selection => { if (!selection) return; switch (selection) { - case NOTIFICATION.TRACK_PARENT_REPO: - trackRepoHandler(); - break; case NOTIFICATION.OPEN_SYNCIGNORE: openSyncIgnoreHandler(); break; diff --git a/src/utils/setup_utils.ts b/src/utils/setup_utils.ts index 223cf47e..bfcab5c5 100644 --- a/src/utils/setup_utils.ts +++ b/src/utils/setup_utils.ts @@ -191,18 +191,11 @@ export const showRepoStatusMsg = (repoPath: string) => { if (repoState.IS_DISCONNECTED) return showDisconnectedRepo(repoPath); if (!repoState.IS_CONNECTED) return showConnectRepo(repoPath); let msg = getRepoInSyncMsg(repoPath); - let button = NOTIFICATION.TRACK_IT; if (repoState.IS_SUB_DIR) { - button = NOTIFICATION.TRACK_PARENT_REPO; msg = getSubDirectoryInSyncMsg(repoPath, repoState.PARENT_REPO_PATH); } // Show notification that repo is in sync - vscode.window.showInformationMessage(msg, button).then(selection => { - if (!selection) return; - if (selection === NOTIFICATION.TRACK_IT) { - trackRepoHandler(); - } - }); + vscode.window.showInformationMessage(msg); }; const registerSyncIgnoreSaveEvent = (repoPath: string) => { diff --git a/src/utils/tab_utils.ts b/src/utils/tab_utils.ts index 22d80c1a..4c0022a7 100644 --- a/src/utils/tab_utils.ts +++ b/src/utils/tab_utils.ts @@ -7,7 +7,7 @@ export const removeTabFile = (filePath: string, funcName: string) => { if (!fs.existsSync(filePath)) return; fs.unlink(filePath, err => { if (!err) return false; - // @ts-ignore + // @ts-expect-error CodeSyncLogger.error(`${funcName}: Error deleting file`, err); }); }; @@ -18,5 +18,4 @@ export const captureTabs = (repoPath: string, isTabEvent: boolean = true) => { const createdAt = formatDatetime(new Date().getTime()); // Adding setTimeout here since 'isActive' key in tabs was not being properly assigned setTimeout(() => handler.handleTabChangeEvent(createdAt, isTabEvent), 1); -} - +}; diff --git a/src/utils/upload_utils.ts b/src/utils/upload_utils.ts index 1f907de1..f63b3e08 100644 --- a/src/utils/upload_utils.ts +++ b/src/utils/upload_utils.ts @@ -5,7 +5,7 @@ import { isBinaryFileSync } from "isbinaryfile"; import { apiRoutes, HttpStatusCodes } from "../constants"; import { PlanLimitsHandler } from './pricing_utils'; import { formatDatetime, readFile } from './common'; -import { s3UploaderUtils } from '../init/s3_uploader'; +import { s3UploaderUtils } from '../connect_repo/s3_uploader'; import { RepoPlanLimitsState } from './repo_state_utils'; diff --git a/tests/extension.test.js b/tests/extension.test.js index c88e5774..b4dad932 100644 --- a/tests/extension.test.js +++ b/tests/extension.test.js @@ -419,7 +419,6 @@ describe("Extension: activate", () => { // Should show Welcome msg expect(vscode.window.showInformationMessage).toHaveBeenCalledTimes(1); expect(vscode.window.showInformationMessage.mock.calls[0][0]).toBe(msg); - expect(vscode.window.showInformationMessage.mock.calls[0][1]).toBe(NOTIFICATION.TRACK_IT); expect(vscode.window.showErrorMessage).toHaveBeenCalledTimes(0); }); @@ -506,7 +505,6 @@ describe("Extension: activate", () => { // Should show Welcome msg expect(vscode.window.showInformationMessage).toHaveBeenCalledTimes(1); expect(vscode.window.showInformationMessage.mock.calls[0][0]).toBe(msg); - expect(vscode.window.showInformationMessage.mock.calls[0][1]).toBe(NOTIFICATION.TRACK_PARENT_REPO); }); test("With active user, repo is sub directory and syncignored", async () => { @@ -551,7 +549,6 @@ describe("Extension: activate", () => { expect(vscode.window.showInformationMessage).toHaveBeenCalledTimes(1); expect(vscode.window.showInformationMessage.mock.calls[0][0]).toBe(msg); expect(vscode.window.showInformationMessage.mock.calls[0][1]).toBe(NOTIFICATION.OPEN_SYNCIGNORE); - expect(vscode.window.showInformationMessage.mock.calls[0][2]).toBe(NOTIFICATION.TRACK_PARENT_REPO); - expect(vscode.window.showInformationMessage.mock.calls[0][3]).toBe(NOTIFICATION.DISCONNECT_PARENT_REPO); + expect(vscode.window.showInformationMessage.mock.calls[0][2]).toBe(NOTIFICATION.DISCONNECT_PARENT_REPO); }); }); diff --git a/tests/test_codesyncd/detect_branch_change.test.js b/tests/test_codesyncd/detect_branch_change.test.js index 35270aed..b8f15697 100644 --- a/tests/test_codesyncd/detect_branch_change.test.js +++ b/tests/test_codesyncd/detect_branch_change.test.js @@ -9,7 +9,7 @@ import fetchMock from "jest-fetch-mock"; import {DEFAULT_BRANCH} from "../../src/constants"; import {pathUtils} from "../../src/utils/path_utils"; import {readYML} from "../../src/utils/common"; -import {initUtils} from "../../src/init/utils"; +import {initUtils} from "../../src/connect_repo/utils"; import {detectBranchChange} from "../../src/codesyncd/populate_buffer"; import {CodeSyncState, CODESYNC_STATES} from "../../src/utils/state_utils"; @@ -172,7 +172,9 @@ describe("detectBranchChange", () => { _configData.repos[repoPath] = { id: generateRandomNumber(1, 100000), branches: {}, - email: TEST_EMAIL + email: TEST_EMAIL, + orgId: null, + teamId: null }; _configData.repos[repoPath].branches[DEFAULT_BRANCH] = { "file_1.js": null diff --git a/tests/test_codesyncd/utils.test.js b/tests/test_codesyncd/utils.test.js index 9741435b..d9bae60b 100644 --- a/tests/test_codesyncd/utils.test.js +++ b/tests/test_codesyncd/utils.test.js @@ -31,7 +31,7 @@ import { import {DEFAULT_BRANCH} from "../../src/constants"; import {readYML} from "../../src/utils/common"; import {pathUtils} from "../../src/utils/path_utils"; -import {s3UploaderUtils} from "../../src/init/s3_uploader"; +import {s3UploaderUtils} from "../../src/connect_repo/s3_uploader"; describe("isValidDiff", () => { @@ -276,18 +276,18 @@ describe("cleanUpDeleteDiff", () => { fs.rmSync(baseRepoPath, { recursive: true, force: true }); }); - test("Should cleanup file from system directories", () => { + test("Should cleanup file from system directories", async () => { expect(fs.existsSync(shadowFilePath)).toBe(true); expect(fs.existsSync(originalsFilePath)).toBe(true); expect(fs.existsSync(cacheFilePath)).toBe(true); cleanUpDeleteDiff(repoPath, DEFAULT_BRANCH, fileRelPath, configData); + await waitFor(1); expect(fs.existsSync(shadowFilePath)).toBe(false); expect(fs.existsSync(originalsFilePath)).toBe(false); expect(fs.existsSync(cacheFilePath)).toBe(false); const config = readYML(configPath); expect(fileRelPath in config.repos[repoPath].branches[DEFAULT_BRANCH]).toBe(false); }); - }); describe("getDIffForDeletedFile", () => { diff --git a/tests/test_init/handler.test.js b/tests/test_init/handler.test.js index d4ff0164..e3ce6745 100644 --- a/tests/test_init/handler.test.js +++ b/tests/test_init/handler.test.js @@ -6,7 +6,7 @@ import isOnline from 'is-online'; import untildify from 'untildify'; import { DEFAULT_BRANCH, GITIGNORE, NOTIFICATION, SYNCIGNORE } from "../../src/constants"; import fetchMock from "jest-fetch-mock"; -import { initHandler } from "../../src/init/init_handler"; +import { initHandler } from "../../src/connect_repo/connect_repo_handler"; import { Config, DUMMY_FILE_CONTENT, @@ -27,7 +27,7 @@ import { pathUtils } from "../../src/utils/path_utils"; import { readYML, readFile } from "../../src/utils/common"; import { createSystemDirectories } from "../../src/utils/setup_utils"; import { CodeSyncState, CODESYNC_STATES } from "../../src/utils/state_utils"; -import { s3UploaderUtils } from "../../src/init/s3_uploader"; +import { s3UploaderUtils } from "../../src/connect_repo/s3_uploader"; describe("initHandler: connectRepo", () => { diff --git a/tests/test_init/utils.test.js b/tests/test_init/utils.test.js index 34f2b5c8..034cc91b 100644 --- a/tests/test_init/utils.test.js +++ b/tests/test_init/utils.test.js @@ -5,7 +5,7 @@ import yaml from "js-yaml"; import vscode from "vscode"; import isOnline from 'is-online'; import untildify from 'untildify'; -import {initUtils} from "../../src/init/utils"; +import {initUtils} from "../../src/connect_repo/utils"; import { ANOTHER_TEST_EMAIL, @@ -24,7 +24,7 @@ import {readYML} from "../../src/utils/common"; import fetchMock from "jest-fetch-mock"; import {pathUtils} from "../../src/utils/path_utils"; import { createSystemDirectories, generateRandomNumber } from "../../src/utils/setup_utils"; -import { s3UploaderUtils } from "../../src/init/s3_uploader"; +import { s3UploaderUtils } from "../../src/connect_repo/s3_uploader"; describe("getSyncablePaths", () => { diff --git a/tests/test_utils/auth_utils.test.js b/tests/test_utils/auth_utils.test.js index dfb30071..db832f22 100644 --- a/tests/test_utils/auth_utils.test.js +++ b/tests/test_utils/auth_utils.test.js @@ -131,7 +131,7 @@ describe("logoutHandler", () => { expect(vscode.commands.executeCommand.mock.calls[0][0]).toStrictEqual("setContext"); expect(vscode.commands.executeCommand.mock.calls[0][1]).toStrictEqual("showLogIn"); expect(vscode.commands.executeCommand.mock.calls[0][2]).toBe(true); - await waitFor(1); + await waitFor(2); expect(vscode.window.showInformationMessage).toHaveBeenCalledTimes(1); expect(vscode.window.showInformationMessage.mock.calls[0][0]).toStrictEqual(NOTIFICATION.LOGGED_OUT_SUCCESSFULLY); }); diff --git a/tests/test_utils/setup_utils.test.js b/tests/test_utils/setup_utils.test.js index 866d7a61..245a25a0 100644 --- a/tests/test_utils/setup_utils.test.js +++ b/tests/test_utils/setup_utils.test.js @@ -183,7 +183,6 @@ describe("setupCodeSync", () => { expect(vscode.window.showInformationMessage).toHaveBeenCalledTimes(1); const msg = getRepoInSyncMsg(repoPath); expect(vscode.window.showInformationMessage.mock.calls[0][0]).toBe(msg); - expect(vscode.window.showInformationMessage.mock.calls[0][1]).toBe(NOTIFICATION.TRACK_IT); fs.rmSync(userFilePath); }); @@ -199,7 +198,6 @@ describe("setupCodeSync", () => { expect(vscode.window.showInformationMessage).toHaveBeenCalledTimes(1); const msg = getSubDirectoryInSyncMsg(subDir, repoPath); expect(vscode.window.showInformationMessage.mock.calls[0][0]).toBe(msg); - expect(vscode.window.showInformationMessage.mock.calls[0][1]).toBe(NOTIFICATION.TRACK_PARENT_REPO); fs.rmSync(userFilePath); }); @@ -218,8 +216,7 @@ describe("setupCodeSync", () => { const msg = getDirectorySyncIgnoredMsg(subDir, repoPath); expect(vscode.window.showInformationMessage.mock.calls[0][0]).toBe(msg); expect(vscode.window.showInformationMessage.mock.calls[0][1]).toBe(NOTIFICATION.OPEN_SYNCIGNORE); - expect(vscode.window.showInformationMessage.mock.calls[0][2]).toBe(NOTIFICATION.TRACK_PARENT_REPO); - expect(vscode.window.showInformationMessage.mock.calls[0][3]).toBe(NOTIFICATION.DISCONNECT_PARENT_REPO); + expect(vscode.window.showInformationMessage.mock.calls[0][2]).toBe(NOTIFICATION.DISCONNECT_PARENT_REPO); fs.rmSync(userFilePath); });