[MM-36432][MM-37072][MM-37073] Logic to support Focalboard and Playbooks tabs (#1680)

* Tab stuff

* Inter-tab navigation

* Close tab functionality

* [MM-36342][MM-37072] Logic to support Focalboard and Playbooks tabs

* Update to version 5.0

* Update config.yml

* Updated routes

* Update names for products

* [MM-37073] Close unneeded tabs when not using v6.0

* Merge'd

* Update config.yml

* Update config.yml

* Fix menu names

* PR feedback

* blank

* blank

* blank

* PR feedback

* Update config.yml

* PR feedback

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
Devin Binnie
2021-09-01 12:45:37 -04:00
committed by GitHub
parent 58bb16fbb6
commit 37c637efe9
27 changed files with 570 additions and 232 deletions

View File

@@ -3,6 +3,8 @@
export const SWITCH_SERVER = 'switch-server';
export const SWITCH_TAB = 'switch-tab';
export const CLOSE_TAB = 'close-tab';
export const OPEN_TAB = 'open-tab';
export const SET_ACTIVE_VIEW = 'set-active-view';
export const MARK_READ = 'mark-read';
export const FOCUS_BROWSERVIEW = 'focus-browserview';
@@ -92,3 +94,5 @@ export const UPDATE_DROPDOWN_MENTIONS = 'update-dropdown-mentions';
export const REQUEST_TEAMS_DROPDOWN_INFO = 'request-teams-dropdown-info';
export const RECEIVE_DROPDOWN_MENU_SIZE = 'receive-dropdown-menu-size';
export const SEND_DROPDOWN_MENU_SIZE = 'send-dropdown-menu-size';
export const BROWSER_HISTORY_PUSH = 'browser-history-push';

View File

@@ -1,12 +1,14 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {getFormattedPathName} from 'common/utils/url';
import BaseTabView from './BaseTabView';
import {TabType, TAB_FOCALBOARD} from './TabView';
export default class FocalboardTabView extends BaseTabView {
get url(): URL {
return this.server.url;
return new URL(`${this.server.url.origin}${getFormattedPathName(this.server.url.pathname)}boards`);
}
get type(): TabType {

View File

@@ -1,12 +1,14 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {getFormattedPathName} from 'common/utils/url';
import BaseTabView from './BaseTabView';
import {TabType, TAB_PLAYBOOKS} from './TabView';
export default class PlaybooksTabView extends BaseTabView {
get url(): URL {
return this.server.url;
return new URL(`${this.server.url.origin}${getFormattedPathName(this.server.url.pathname)}playbooks`);
}
get type(): TabType {

View File

@@ -29,14 +29,17 @@ export function getDefaultTeamWithTabsFromTeam(team: Team) {
{
name: TAB_MESSAGING,
order: 0,
isClosed: false,
},
{
name: TAB_FOCALBOARD,
order: 1,
isClosed: false,
},
{
name: TAB_PLAYBOOKS,
order: 2,
isClosed: false,
},
],
};
@@ -59,3 +62,21 @@ export function getServerView(srv: MattermostServer, tab: Tab) {
export function getTabViewName(serverName: string, tabType: string) {
return `${serverName}___${tabType}`;
}
export function getTabDisplayName(tabType: TabType) {
switch (tabType) {
case TAB_MESSAGING:
return 'Channels';
case TAB_FOCALBOARD:
return 'Boards';
case TAB_PLAYBOOKS:
return 'Playbooks';
default:
throw new Error('Not implemeneted');
}
}
export function canCloseTab(tabType: TabType) {
// TODO: maybe rework to make the property belong to the class somehow
return tabType !== TAB_MESSAGING;
}

View File

@@ -79,10 +79,14 @@ function getServerInfo(serverUrl: URL | string) {
// does the server have a subpath?
const pn = parsedServer.pathname.toLowerCase();
const subpath = pn.endsWith('/') ? pn.toLowerCase() : `${pn}/`;
const subpath = getFormattedPathName(pn);
return {subpath, url: parsedServer};
}
export function getFormattedPathName(pn: string) {
return pn.endsWith('/') ? pn.toLowerCase() : `${pn}/`;
}
function getManagedResources() {
if (!buildConfig) {
return [];
@@ -164,25 +168,24 @@ function getView(inputURL: URL | string, teams: TeamWithTabs[], ignoreScheme = f
if (!parsedURL) {
return undefined;
}
let parsedServerUrl;
let firstOption;
let secondOption;
teams.forEach((team) => {
const srv = new MattermostServer(team.name, team.url);
team.tabs.forEach((tab) => {
const tabView = getServerView(srv, tab);
parsedServerUrl = parseURL(tabView.url);
const parsedServerUrl = parseURL(tabView.url);
if (parsedServerUrl) {
// check server and subpath matches (without subpath pathname is \ so it always matches)
if (equalUrlsWithSubpath(parsedServerUrl, parsedURL, ignoreScheme)) {
firstOption = {name: tabView.name, url: parsedServerUrl};
firstOption = {name: tabView.name, url: parsedServerUrl.toString()};
}
if (equalUrlsIgnoringSubpath(parsedServerUrl, parsedURL, ignoreScheme)) {
// in case the user added something on the path that doesn't really belong to the server
// there might be more than one that matches, but we can't differentiate, so last one
// is as good as any other in case there is no better match (e.g.: two subpath servers with the same origin)
// e.g.: https://community.mattermost.com/core
secondOption = {name: tabView.name, url: parsedServerUrl};
secondOption = {name: tabView.name, url: parsedServerUrl.toString()};
}
}
});
@@ -214,7 +217,8 @@ function isTrustedURL(url: URL | string, teams: TeamWithTabs[]) {
}
function isCustomLoginURL(url: URL | string, server: ServerFromURL, teams: TeamWithTabs[]): boolean {
const subpath = server ? server.url.pathname : '';
const serverURL = parseURL(server.url);
const subpath = server && serverURL ? serverURL.pathname : '';
const parsedURL = parseURL(url);
if (!parsedURL) {
return false;

View File

@@ -37,8 +37,34 @@ function shorten(string: string, max?: number) {
return string;
}
export function isServerVersionGreaterThanOrEqualTo(currentVersion: string, compareVersion: string): boolean {
if (currentVersion === compareVersion) {
return true;
}
// We only care about the numbers
const currentVersionNumber = (currentVersion || '').split('.').filter((x) => (/^[0-9]+$/).exec(x) !== null);
const compareVersionNumber = (compareVersion || '').split('.').filter((x) => (/^[0-9]+$/).exec(x) !== null);
for (let i = 0; i < Math.max(currentVersionNumber.length, compareVersionNumber.length); i++) {
const currentVersion = parseInt(currentVersionNumber[i], 10) || 0;
const compareVersion = parseInt(compareVersionNumber[i], 10) || 0;
if (currentVersion > compareVersion) {
return true;
}
if (currentVersion < compareVersion) {
return false;
}
}
// If all components are equal, then return true
return true;
}
export default {
getDisplayBoundaries,
runMode,
shorten,
isServerVersionGreaterThanOrEqualTo,
};