Path: blob/master/src/packages/frontend/app/sign-in-action.ts
5980 views
/*1Do something somewhat friendly when a user signs in for the first time,2either after creating an account or being signed out.34For now:56- ensure they are a collab on at least one project7- open the most recent project they actively used and show the +New page89That's it for now.10*/1112import { delay } from "awaiting";13import { redux } from "@cocalc/frontend/app-framework";14import { once } from "@cocalc/util/async-utils";15import { webapp_client } from "@cocalc/frontend/webapp-client";16import { cmp } from "@cocalc/util/misc";17import { QueryParams } from "@cocalc/frontend/misc/query-params";1819export default async function signInAction() {20const signIn = QueryParams.get("sign-in");21if (signIn == null) {22return;23}24QueryParams.remove("sign-in");25await delay(1); // so projects store is created (not in sync initial load loop)26const project_id = await getProject();27const actions = redux.getActions("projects");28actions.open_project({ project_id, switch_to: true, target: "new" });29await actions.start_project(project_id);30}3132async function create(title = "My First Project") {33const project_id = await webapp_client.project_client.create({34title,35description: "",36});37const projects = redux.getStore("projects");38// wait until projects_map is loaded, so we know what projects the users has (probably)39while (projects.getIn(["project_map", project_id]) == null) {40await once(projects, "change");41}42return project_id;43}4445async function getProject(): Promise<string> {46const projects = redux.getStore("projects");47// wait until projects_map is loaded, so we know what projects the users has (probably)48while (projects.get("project_map") == null) {49await once(projects, "change");50}51const account = redux.getStore("account");52while (account.get("created") == null) {53await once(account, "change");54}5556const created = account.get("created");57let project_map = projects.get("project_map")!;58if (project_map.size == 0) {59// no known projects -- could be a new account, or could be an old account and no *recent* projects60if (61(created?.valueOf() ?? Date.now()) >=62Date.now() - 2 * 24 * 60 * 60 * 100063) {64// new account -- make a project65return await create("My First Project");66} else {67// old account but no projects -- try loading all.68const projectActions = redux.getActions("projects");69await projectActions.load_all_projects();70project_map = projects.get("project_map")!;71if (project_map.size == 0) {72// still nothing -- just create73return await create();74}75}76}7778const account_id = account.get("account_id");7980// now there should be at least one project in project_map.81// Is there a non-deleted non-hidden project?82const options: any[] = [];83for (const [_, project] of project_map) {84if (project.get("deleted")) {85continue;86}87if (project.getIn(["users", account_id, "hide"])) {88continue;89}90options.push(project);91}92if (options.length == 0) {93return await create();94}9596// Sort the projects by when YOU were last active on the project, or if you were97// never active on any project, by when the projects was last_edited.98const usedByYou = options.filter((x) => x.getIn(["last_active", account_id]));99100if (usedByYou.length == 0) {101// you were never active on any project, so just return project most recently edited102options.sort((x, y) => -cmp(x.get("last_edited"), y.get("last_edited")));103return options[0].get("project_id");104}105106usedByYou.sort(107(x, y) =>108-cmp(109x.getIn(["last_active", account_id]),110y.getIn(["last_active", account_id]),111),112);113return usedByYou[0].get("project_id");114}115116117