Compare commits

..
Author SHA1 Message Date
Benjamin Perez 4797f9933c Build 2023-04-14 15:35:15 -06:00
Benjamin Perez 71b8cae209 Adjusted size of sort arrow in data table 2023-04-14 15:34:09 -06:00
Benjamin Perez 22013b1853 Fixed sx var in InputBox
(cherry picked from commit e9e62a134e2e81bbca5860597b213e1bc11b3bd6)

Breadcrumsb types

(cherry picked from commit cf0efda19f5a5a43d56f9c2d41aff8d05a52c163)

Added custom styling capability to mds

(cherry picked from commit 9b589cc02eb906b7e39fa8f2a31ac168ceba4ba5)
2023-04-14 15:05:29 -06:00
4348 changed files with 75324 additions and 218282 deletions
-49
View File
@@ -1,49 +0,0 @@
name: Build Container
on:
release:
types:
- published
concurrency:
group: ${{ github.workflow }}-deployer-${{ github.head_ref }}
cancel-in-progress: true
jobs:
build-and-release:
name: "Build"
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
steps:
- name: Check out Code
uses: actions/checkout@v3
- name: Read .nvmrc
id: node_version
run: echo "$(cat .nvmrc)" && echo "NVMRC=$(cat .nvmrc)" >> $GITHUB_ENV
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NVMRC }}
cache: "yarn"
cache-dependency-path: yarn.lock
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build Storybook
run: |
yarn install --immutable
yarn build
yarn build-storybook
docker buildx build --platform linux/amd64 --push -t registry.min.dev/minio/mds .
echo "${{ secrets.MDS_DEPLOYER_KUBECONFIG }}" > /tmp/kubecconfig
ls -l /tmp/kubecconfig
kubectl --kubeconfig /tmp/kubecconfig -n mds delete pod $(kubectl --kubeconfig /tmp/kubecconfig -n mds get pods | grep mds | awk '{print $1}')
+19 -12
View File
@@ -20,22 +20,12 @@ jobs:
matrix:
os: [ubuntu-latest]
steps:
- name: Check out Code
uses: actions/checkout@v3
- name: Read .nvmrc
id: node_version
run: echo "$(cat .nvmrc)" && echo "NVMRC=$(cat .nvmrc)" >> $GITHUB_ENV
- uses: actions/setup-node@v3
with:
node-version: ${{ env.NVMRC }}
- uses: actions/checkout@v2
- name: Install Dependencies
continue-on-error: false
run: |
corepack enable
yarn install --immutable
yarn install
- name: Check if build is correct
continue-on-error: false
@@ -46,3 +36,20 @@ jobs:
continue-on-error: false
run: |
./check-prettier.sh
run-components-tests:
name: "Components validation tests"
needs:
- review-warnings-and-build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: yarn install
- name: Run Jest Tests
run: yarn test
-8
View File
@@ -12,11 +12,3 @@ node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
-1
View File
@@ -1 +0,0 @@
18
-1
View File
@@ -1 +0,0 @@
{}
+6 -14
View File
@@ -1,12 +1,10 @@
import remarkGfm from "remark-gfm";
module.exports = {
stories: ["../src/**/**/*.mdx", "../src/**/**/*.stories.@(js|jsx|ts|tsx)"],
core: {
disableTelemetry: true,
},
stories: [
"../src/**/**/*.stories.mdx",
"../src/**/**/*.stories.@(js|jsx|ts|tsx)",
],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
@@ -22,18 +20,12 @@ module.exports = {
},
},
},
"@storybook/addon-webpack5-compiler-babel",
"@chromatic-com/storybook",
],
framework: {
name: "@storybook/react-webpack5",
options: {},
},
docs: {},
typescript: {
reactDocgen: "react-docgen-typescript",
docs: {
autodocs: true,
},
};
+1 -2
View File
@@ -2,7 +2,7 @@ import { themes } from "@storybook/theming";
import { darkColors, lightColors } from "../src/global/themes";
export const parameters = {
actions: {},
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
@@ -38,4 +38,3 @@ export const parameters = {
},
},
};
export const tags = ["autodocs"];
-3
View File
@@ -1,3 +0,0 @@
checksumBehavior: reset
nodeLinker: node-modules
+1 -2
View File
@@ -1,4 +1,3 @@
FROM nginx:1
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
COPY docs /usr/share/nginx/html
-3
View File
@@ -8,6 +8,3 @@ lint:
test:
@(yarn install; yarn test;)
test-warnings:
./check-warnings.sh
+2 -1
View File
@@ -1,3 +1,4 @@
#!/bin/bash
yarn dlx prettier --check ./src
yarn install
yarn prettier --check ./src
-19
View File
@@ -1,19 +0,0 @@
#!/bin/bash
yell() { echo "$0: $*" >&2; }
die() {
yell "$*"
cat yarn.log
exit 111
}
try() { "$@" &> yarn.log || die "cannot $*"; }
rm -f yarn.log
try make build
if cat yarn.log | grep "Compiled with warnings"; then
echo "There are warnings in the code"
exit 1
fi
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-92
View File
@@ -1,92 +0,0 @@
Geist Sans and Geist Mono Font
(C) 2023 Vercel, made in collaboration with basement.studio
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is available with a FAQ at: http://scripts.sil.org/OFL and copied below
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION AND CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
+22630
View File
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
@@ -0,0 +1,22 @@
import React from "react";
import { CSSObject } from "styled-components";
export interface ActionItem {
action: () => void;
label: string;
disabled: boolean;
icon: React.ReactNode;
tooltip: string;
}
export interface ActionsListProps {
sx?: CSSObject;
items: ActionItem[];
title: React.ReactNode;
}
export interface ActionsListPanelProps {
sx?: CSSObject;
}
export interface ActionButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
label: string;
icon: React.ReactNode;
}
@@ -0,0 +1,11 @@
export interface ApplicationLogoProps {
applicationName:
| "console"
| "operator"
| "directpv"
| "kes"
| "subnet"
| "subnetops";
subVariant?: "simple" | "AGPL" | "standard" | "enterprise";
inverse?: boolean;
}
@@ -0,0 +1,9 @@
import React from "react";
import { LogoBaseProps } from "./LogoBase.types";
declare const LogoBase: import("styled-components").StyledComponent<
"svg",
any,
React.SVGProps<any> & LogoBaseProps,
never
>;
export default LogoBase;
@@ -0,0 +1,7 @@
import React from "react";
import { CSSProperties } from "styled-components";
export interface BackLinkProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
sx?: CSSProperties;
label?: string;
}
+4
View File
@@ -0,0 +1,4 @@
import { FC, HTMLAttributes } from "react";
import { BoxProps } from "./Box.types";
declare const Box: FC<HTMLAttributes<HTMLDivElement> & BoxProps>;
export default Box;
+7
View File
@@ -0,0 +1,7 @@
import React from "react";
import { CSSObject } from "styled-components";
export interface BoxProps {
sx?: CSSObject;
children?: React.ReactNode;
withBorders?: boolean;
}
@@ -0,0 +1,11 @@
import React from "react";
import { CSSObject } from "styled-components";
export interface BreadcrumbsProps {
sx?: CSSObject;
children: React.ReactNode;
additionalOptions?: React.ReactNode;
goBackFunction: () => void;
}
export interface BreadcrumbsContainerProps {
sx?: CSSObject;
}
+19
View File
@@ -0,0 +1,19 @@
import { MouseEventHandler, ReactNode } from "react";
import { CSSObject } from "styled-components";
export interface ButtonProps {
id: string;
name?: string;
label?: string;
variant?: "regular" | "callAction" | "secondary" | "text";
icon?: ReactNode;
iconLocation?: "start" | "end";
fullWidth?: boolean;
disabled?: boolean;
collapseOnSmall?: boolean;
onClick?: MouseEventHandler<HTMLButtonElement>;
children?: ReactNode | string;
sx?: CSSObject;
}
export interface ConstructProps {
parentChildren: ReactNode | string | undefined;
}
@@ -0,0 +1,8 @@
import { HTMLAttributes } from "react";
import { CSSObject } from "styled-components";
export interface CheckboxProps extends HTMLAttributes<HTMLInputElement> {
label?: string;
tooltip?: string;
overrideLabelClasses?: string;
overrideCheckboxStyles?: CSSObject;
}
+4
View File
@@ -0,0 +1,4 @@
import { FC } from "react";
import { DataTableProps } from "./DataTable.types";
declare const DataTable: FC<DataTableProps>;
export default DataTable;
@@ -0,0 +1,80 @@
import React, { HTMLAttributes } from "react";
import { CSSObject } from "styled-components";
export interface ItemActions {
label?: string;
type: string | any;
sendOnlyId?: boolean;
disableButtonFunction?: (itemValue: any) => boolean;
showLoaderFunction?: (itemValue: any) => boolean;
onClick?(valueToSend: any): any;
}
export interface IColumns {
label: string;
elementKey?: string;
renderFunction?: (input: any) => any;
renderFullObject?: boolean;
globalClass?: any;
rowClass?: any;
width?: number;
headerTextAlign?: string;
contentTextAlign?: string;
enableSort?: boolean;
}
export interface IInfiniteScrollConfig {
loadMoreRecords: (indexElements: {
startIndex: number;
stopIndex: number;
}) => Promise<any>;
recordsCount: number;
}
export interface ISortConfig {
triggerSort: (val: any) => any;
currentSort: string;
currentDirection: "ASC" | "DESC" | undefined;
}
export interface DataTableProps {
itemActions?: ItemActions[] | null;
columns: IColumns[];
onSelect?: (e: React.ChangeEvent<HTMLInputElement>) => void;
idField?: string;
isLoading?: boolean;
loadingMessage?: React.ReactNode;
records: any[];
entityName?: string;
selectedItems?: string[];
customEmptyMessage?: string;
customPaperHeight?: string;
noBackground?: boolean;
columnsSelector?: boolean;
textSelectable?: boolean;
columnsShown?: string[];
onColumnChange?: (column: string, state: boolean) => any;
autoScrollToBottom?: boolean;
infiniteScrollConfig?: IInfiniteScrollConfig;
sortConfig?: ISortConfig;
disabled?: boolean;
onSelectAll?: () => void;
rowStyle?: ({
index,
}: {
index: number;
}) => "deleted" | "" | React.CSSProperties;
parentClassName?: string;
sx?: CSSObject;
}
export interface DataTableWrapperProps extends HTMLAttributes<HTMLDivElement> {
disabled?: boolean;
customPaperHeight?: string | number;
noBackground?: boolean;
sx?: CSSObject;
}
export interface IActionButton {
label?: string;
type: string | React.ReactNode;
onClick?: (id: string) => any;
valueToSend: any;
selected: boolean;
sendOnlyId?: boolean;
idField: string;
disabled: boolean;
}
@@ -0,0 +1,25 @@
import { IColumns, ItemActions } from "./DataTable.types";
export declare const selectWidth = 45;
export declare const generateColumnsMap: (
columns: IColumns[],
containerWidth: number,
actionsWidth: number,
hasSelect: boolean,
hasActions: boolean,
selectedItems: string[],
idField: string,
columnsSelector: boolean,
columnsShown: string[],
sortColumn: string,
sortDirection: "ASC" | "DESC" | undefined
) => (JSX.Element | null)[];
export declare const elementActions: (
actions: ItemActions[],
valueToSend: any,
selected: boolean,
idField: string
) => (JSX.Element | null)[];
export declare const calculateOptionsSize: (
containerWidth: number,
totalOptions: number
) => number;
@@ -0,0 +1,4 @@
import { FC } from "react";
import { IActionButton } from "./DataTable.types";
declare const TableActionButton: FC<IActionButton>;
export default TableActionButton;
@@ -0,0 +1,9 @@
import React from "react";
import { CSSObject } from "styled-components";
export interface FormLayoutProps {
sx?: CSSObject;
children?: React.ReactNode;
title?: string;
icon?: React.ReactNode;
helpBox?: React.ReactNode;
}
@@ -0,0 +1,5 @@
declare const GlobalStyles: import("styled-components").GlobalStyleComponent<
{},
import("styled-components").DefaultTheme
>;
export default GlobalStyles;
+35
View File
@@ -0,0 +1,35 @@
import { HTMLAttributes, ReactNode } from "react";
import { CSSObject } from "styled-components";
interface GridCommonProps extends HTMLAttributes<HTMLDivElement> {
children?: ReactNode;
sx?: CSSObject;
}
type ConditionalProps =
| {
container?: boolean;
item?: never;
wrap?: "nowrap" | "wrap-reverse" | "wrap";
direction?: "column-reverse" | "column" | "row-reverse" | "row";
columnSpacing?: number;
rowSpacing?: number;
xs?: never;
sm?: never;
md?: never;
lg?: never;
xl?: never;
}
| {
container?: never;
item?: boolean;
wrap?: never;
direction?: never;
columnSpacing?: never;
rowSpacing?: never;
xs?: "auto" | "hidden" | number | boolean;
sm?: "auto" | "hidden" | number | boolean;
md?: "auto" | "hidden" | number | boolean;
lg?: "auto" | "hidden" | number | boolean;
xl?: "auto" | "hidden" | number | boolean;
};
export type GridProps = GridCommonProps & ConditionalProps;
export {};
+4
View File
@@ -0,0 +1,4 @@
import { FC } from "react";
import { HelpBoxProps } from "./HelpBox.types";
declare const HelpBox: FC<HelpBoxProps>;
export default HelpBox;
+6
View File
@@ -0,0 +1,6 @@
import React from "react";
export interface HelpBoxProps {
iconComponent: any;
title: string | React.ReactNode;
help: any;
}
@@ -0,0 +1,9 @@
import React from "react";
import { CSSObject } from "styled-components";
export interface IconButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
label?: string;
size?: "small" | "medium" | "large" | string;
sx?: CSSObject;
children: React.ReactNode;
}
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AGPLV3DarkLogo: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AGPLV3DarkLogo;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AGPLV3LightLogo: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AGPLV3LightLogo;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AGPLV3Logo: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AGPLV3Logo;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AccessRuleIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AccessRuleIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AccountIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AccountIcon;
@@ -0,0 +1,5 @@
import { SVGProps } from "react";
declare const AddAccessRuleIcon: (
props: SVGProps<SVGSVGElement>
) => JSX.Element;
export default AddAccessRuleIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AddFolderIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AddFolderIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AddIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AddIcon;
@@ -0,0 +1,5 @@
import { SVGProps } from "react";
declare const AddMembersToGroupIcon: (
props: SVGProps<SVGSVGElement>
) => JSX.Element;
export default AddMembersToGroupIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AddNewTagIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AddNewTagIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AlertCloseIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AlertCloseIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AlertIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AlertIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AllBucketsIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AllBucketsIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const ArrowDropUp: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default ArrowDropUp;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const ArrowDropUp: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default ArrowDropUp;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const ArrowIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default ArrowIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const ArrowRightIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default ArrowRightIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const ArrowRightLink: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default ArrowRightLink;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AzureTierIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AzureTierIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const AzureTierIconXs: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default AzureTierIconXs;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const BackCaretIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default BackCaretIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const BackIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default BackIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const BackSettingsIcon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default BackSettingsIcon;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const BoxArrowDown: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default BoxArrowDown;
+3
View File
@@ -0,0 +1,3 @@
import { SVGProps } from "react";
declare const BoxArrowUp: (props: SVGProps<SVGSVGElement>) => JSX.Element;
export default BoxArrowUp;
@@ -0,0 +1,5 @@
import { SVGProps } from "react";
declare const BucketEncryptionIcon: (
props: SVGProps<SVGSVGElement>
) => JSX.Element;
export default BucketEncryptionIcon;

Some files were not shown because too many files have changed in this diff Show More