├── .nvmrc ├── .node-version ├── __mocks__ └── styleMock.js ├── app ├── css │ ├── outline.css │ ├── backdrop.css │ ├── index.js │ ├── rounded.css │ ├── details.css │ ├── icons.css │ ├── font-weights.css │ ├── cursor.css │ ├── interaction-events.css │ ├── shadows.css │ ├── letter-spacing.css │ ├── hover-fading.css │ ├── form.css │ ├── radio.css │ ├── checkbox.css │ ├── emoji.css │ ├── background-hover-colors.css │ ├── border-child.css │ ├── display.css │ ├── hover-underline.css │ ├── focus-colors.css │ ├── fonts.css │ ├── svg-colors.css │ ├── scrollbar.css │ ├── btn-outline.css │ ├── text.css │ ├── reset.css │ ├── select.css │ ├── rouge.css │ ├── btn.css │ ├── btn-primary.css │ ├── container.css │ ├── input.css │ ├── colors.css │ ├── style-guide │ │ └── index.js │ ├── background-colors.css │ ├── main.css │ ├── backgrounds.css │ ├── border-colors.css │ └── variables.css ├── components │ ├── shared │ │ ├── Icon │ │ │ ├── __mocks__ │ │ │ │ └── svgContent.js │ │ │ ├── placeholder.svg │ │ │ ├── plus.svg │ │ │ ├── down-triangle.svg │ │ │ ├── menu.svg │ │ │ ├── chevron-right.svg │ │ │ ├── permission-small-tick.svg │ │ │ ├── build-skipping.svg │ │ │ ├── schedules.svg │ │ │ ├── close.svg │ │ │ ├── badges.svg │ │ │ ├── permission-small-cross.svg │ │ │ ├── search.svg │ │ │ ├── circle.svg │ │ │ ├── queues.svg │ │ │ ├── sso.svg │ │ │ ├── pipeline.svg │ │ │ ├── plus-circle.svg │ │ │ ├── github.svg │ │ │ ├── twitter.svg │ │ │ ├── svgContent.js │ │ │ ├── billing.svg │ │ │ ├── RevealableDownChevron.js │ │ │ ├── teams.svg │ │ │ ├── emails.svg │ │ │ ├── index.js │ │ │ ├── notification-services.svg │ │ │ ├── gitlab.svg │ │ │ ├── connected-apps.svg │ │ │ ├── retry.svg │ │ │ ├── api-tokens.svg │ │ │ └── two-factor.svg │ │ ├── SectionLoader.js │ │ ├── TabControl │ │ │ └── index.js │ │ ├── Autocomplete │ │ │ ├── loader.js │ │ │ └── error-message.js │ │ ├── PageWithContainer.js │ │ ├── FormYAMLEditorField │ │ │ └── codemirror.js │ │ ├── __snapshots__ │ │ │ ├── BuildStatusDescription.spec.js.snap │ │ │ ├── labelledFormComponent.spec.js.snap │ │ │ └── Emojify.spec.js.snap │ │ ├── PermissionSelectOptionDescriptions.js │ │ ├── Menu │ │ │ └── header.js │ │ ├── FormDataList.js │ │ ├── BetaBadge.js │ │ ├── PageHeader │ │ │ ├── button.js │ │ │ ├── title.js │ │ │ ├── menu.js │ │ │ ├── description.js │ │ │ └── icon.js │ │ ├── PipelineStatus │ │ │ └── index.js │ │ ├── FormTextField.js │ │ ├── FormInputHelp.js │ │ ├── FormTextarea.js │ │ ├── Panel │ │ │ ├── header.js │ │ │ ├── row.js │ │ │ ├── intro-with-button.js │ │ │ └── row-actions.js │ │ ├── PageWithMenu.js │ │ ├── FormInputLabel.js │ │ ├── PermissionDescription.js │ │ ├── UserAvatar.js │ │ ├── FormInputErrors.js │ │ ├── Emojify.js │ │ ├── JobLink.js │ │ ├── Badge.js │ │ ├── JobTitle.js │ │ ├── AutosizingTextarea.js │ │ └── Chooser │ │ │ ├── index.js │ │ │ └── option.js │ ├── team │ │ ├── preview.png │ │ └── Labels.js │ ├── OrganizationShow │ │ ├── constants.js │ │ └── Pipeline │ │ │ ├── constants.js │ │ │ └── Metrics │ │ │ └── index.js │ ├── layout │ │ ├── Navigation │ │ │ ├── logo.svg │ │ │ ├── nav-button-right-arrow.svg │ │ │ └── dropdown-button.js │ │ ├── Footer │ │ │ └── link.js │ │ └── Flashes │ │ │ └── flash.js │ ├── user │ │ ├── graphql │ │ │ ├── GraphQLExplorerDocumentation │ │ │ │ ├── Scalar.js │ │ │ │ ├── Argument.js │ │ │ │ ├── Comment.js │ │ │ │ └── RootField.js │ │ │ ├── defaults.js │ │ │ ├── codemirror.js │ │ │ ├── GraphQLExplorerDocumentationMutation.js │ │ │ ├── GraphQLExplorerDocumentationQuery.js │ │ │ └── query.js │ │ └── TwoFactor │ │ │ └── TwoFactorConfigure │ │ │ ├── TwoFactorConfigureActivate │ │ │ └── buildkite.svg │ │ │ └── TotpDeleteMutation.js │ ├── audit_log │ │ └── Drawer │ │ │ └── shared.js │ ├── docs │ │ ├── 07-windows.mdx │ │ ├── 06-macos.mdx │ │ ├── 08-linux.mdx │ │ ├── 05-docker.mdx │ │ ├── 04-freebsd.mdx │ │ └── 01-ubuntu.mdx │ ├── build │ │ └── CommentsList.js │ ├── agent │ │ ├── shared.js │ │ └── shared.spec.js │ ├── organization │ │ └── SettingsSection.js │ ├── job │ │ └── Index │ │ │ └── search-input.js │ ├── pipeline │ │ ├── SettingsSection.js │ │ ├── teams │ │ │ └── Index │ │ │ │ └── team-suggestion.js │ │ └── schedules │ │ │ └── Show │ │ │ └── build.js │ ├── member │ │ ├── Edit │ │ │ └── index.js │ │ └── Teams │ │ │ └── team.js │ └── icons │ │ └── Favorite.js ├── images │ ├── people │ │ ├── lox.jpg │ │ ├── sj26.jpg │ │ ├── ticky.jpg │ │ ├── eleanor.jpg │ │ ├── harriet.jpg │ │ ├── justin.jpg │ │ ├── keithpitt.jpg │ │ ├── lox-small.jpg │ │ ├── sj26-small.jpg │ │ ├── toolmantim.jpg │ │ ├── justin-small.jpg │ │ ├── ticky-small.jpg │ │ ├── eleanor-small.jpg │ │ ├── harriet-small.jpg │ │ ├── keithpitt-small.jpg │ │ ├── matthew-small.jpg │ │ └── toolmantim-small.jpg │ ├── avatar_default.png │ ├── new-changelog-badge-bottom-corner.svg │ ├── up-pointing-white-nib.svg │ └── mark.svg ├── emoji │ ├── apple.js │ └── buildkite.js ├── queries │ ├── Viewer.js │ ├── APIAccessTokenCode.js │ ├── Organization.js │ ├── Team.js │ ├── Agent.js │ ├── Pipeline.js │ ├── PipelineSchedule.js │ ├── OrganizationMember.js │ └── Build.js ├── constants │ ├── TeamPrivacyConstants.js │ ├── TeamMemberRoleConstants.js │ ├── OrganizationMemberRoleConstants.js │ ├── OrganizationMemberSSOModeConstants.js │ ├── GraphQLErrors.js │ ├── BuildStates.js │ └── JobStates.js ├── lib │ ├── relay │ │ ├── __mocks__ │ │ │ └── makeFetch.js │ │ ├── makeFetch.js │ │ └── environment.js │ ├── words.js │ ├── Bugsnag.js │ ├── dasherize.js │ ├── ValidationErrors.js │ ├── jobCommandOneliner.js │ ├── commits.js │ ├── warn.js │ ├── reactRenderer.js │ ├── number.js │ ├── repositories.js │ ├── repositories.spec.js │ ├── __snapshots__ │ │ ├── commits.spec.js.snap │ │ └── repositories.spec.js.snap │ ├── jobs.js │ ├── words.spec.js │ ├── BootstrapTooltipMixin.js │ └── commits.spec.js ├── public-path.js ├── mutations │ ├── EmailResendVerification.js │ ├── TeamMemberUpdate.js │ ├── TeamPipelineUpdate.js │ ├── OrganizationInvitationResend.js │ ├── APIAccessTokenCodeAuthorize.js │ ├── NoticeDismiss.js │ ├── TeamMemberDelete.js │ ├── PipelineFavorite.js │ ├── TeamPipelineDelete.js │ ├── TeamUpdate.js │ └── OrganizationMemberUpdate.js └── stores │ └── PusherStore.js ├── webpack └── .eslintrc.yml ├── renovate.json ├── .gitmodules ├── flow-typed ├── Features.js └── npm │ ├── babel-polyfill_v6.x.x.js │ ├── flow-bin_v0.x.x.js │ ├── escape-html_v1.x.x.js │ ├── create-react-class_v15.x.x.js │ ├── object-assign_v4.x.x.js │ ├── es6-error_v4.x.x.js │ ├── deepmerge_v2.1.x.js │ ├── react-addons-perf_v15.x.x.js │ ├── fetch-jsonp_v1.x.x.js │ ├── classnames_v2.x.x.js │ ├── query-string_v5.1.x.js │ ├── whatwg-fetch_vx.x.x.js │ ├── word-wrap_vx.x.x.js │ ├── raw-loader_vx.x.x.js │ ├── escape-html_vx.x.x.js │ ├── qrcode.react_vx.x.x.js │ ├── buffer-crc32_vx.x.x.js │ ├── http-server_vx.x.x.js │ ├── query-string_vx.x.x.js │ ├── fetch-jsonp_vx.x.x.js │ ├── ignore-loader_vx.x.x.js │ ├── exports-loader_vx.x.x.js │ ├── imports-loader_vx.x.x.js │ ├── postcss-easings_vx.x.x.js │ ├── babel-preset-flow_vx.x.x.js │ ├── babel-preset-react_vx.x.x.js │ ├── global_v4.x.x.js │ ├── babel-preset-stage-0_vx.x.x.js │ ├── stats-webpack-plugin_vx.x.x.js │ ├── postcss-browser-reporter_vx.x.x.js │ ├── mockdate_vx.x.x.js │ ├── url-loader_vx.x.x.js │ ├── file-loader_vx.x.x.js │ ├── eventemitter3_vx.x.x.js │ ├── react-transform-hmr_vx.x.x.js │ ├── css-variables-loader_vx.x.x.js │ └── babel-preset-react-hmre_vx.x.x.js ├── .dockerignore ├── .buildkite └── steps │ ├── eslint.sh │ ├── flow.sh │ ├── jest.sh │ └── webpack.sh ├── .eslintignore ├── Procfile ├── jest ├── setupTestFrameworkScriptFile.js ├── fileTransformer.js ├── browserMocks.js └── schemaMocks │ ├── addMockFunctionsToSchema.js │ └── DefaultMocks.js ├── .storybook ├── addons.js └── config.js ├── stories ├── components │ └── icons │ │ ├── Pipeline.stories.js │ │ ├── BuildState.stories.js │ │ ├── JobState.stories.js │ │ └── Favorite.stories.js ├── shared │ ├── Spinner.stories.js │ ├── FormYamlEditorField.stories.js │ ├── Icon.stories.js │ └── SearchField.stories.js └── sketchExport.stories.js ├── docker-compose.yml ├── Dockerfile ├── .flowconfig ├── .gitignore ├── html-sketchapp.config.js └── LICENSE.txt /.nvmrc: -------------------------------------------------------------------------------- 1 | 10.11.0 2 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | .nvmrc -------------------------------------------------------------------------------- /__mocks__/styleMock.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/css/outline.css: -------------------------------------------------------------------------------- 1 | .outline-none { 2 | outline: 0; 3 | } -------------------------------------------------------------------------------- /app/css/backdrop.css: -------------------------------------------------------------------------------- 1 | .backdrop-blur { 2 | backdrop-filter: blur(5px); 3 | } -------------------------------------------------------------------------------- /app/css/index.js: -------------------------------------------------------------------------------- 1 | export default require('!css-variables-loader!./main.css'); 2 | -------------------------------------------------------------------------------- /webpack/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | 4 | rules: 5 | no-var: off 6 | -------------------------------------------------------------------------------- /app/components/shared/Icon/__mocks__/svgContent.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export default jest.fn(); 4 | -------------------------------------------------------------------------------- /app/css/rounded.css: -------------------------------------------------------------------------------- 1 | .rounded-2 { border-radius: 6px; } 2 | .rounded-3 { border-radius: 9px; } 3 | -------------------------------------------------------------------------------- /app/css/details.css: -------------------------------------------------------------------------------- 1 | .details-reset summary::-webkit-details-marker { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "prHourlyLimit": 0 6 | } 7 | -------------------------------------------------------------------------------- /app/images/people/lox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/lox.jpg -------------------------------------------------------------------------------- /app/images/people/sj26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/sj26.jpg -------------------------------------------------------------------------------- /app/images/people/ticky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/ticky.jpg -------------------------------------------------------------------------------- /app/components/shared/Icon/placeholder.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/css/icons.css: -------------------------------------------------------------------------------- 1 | .icon-ml { 2 | margin-left: 8px; 3 | } 4 | 5 | .icon-mr { 6 | margin-right: 8px; 7 | } 8 | -------------------------------------------------------------------------------- /app/images/avatar_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/avatar_default.png -------------------------------------------------------------------------------- /app/images/people/eleanor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/eleanor.jpg -------------------------------------------------------------------------------- /app/images/people/harriet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/harriet.jpg -------------------------------------------------------------------------------- /app/images/people/justin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/justin.jpg -------------------------------------------------------------------------------- /app/components/team/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/components/team/preview.png -------------------------------------------------------------------------------- /app/images/people/keithpitt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/keithpitt.jpg -------------------------------------------------------------------------------- /app/images/people/lox-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/lox-small.jpg -------------------------------------------------------------------------------- /app/images/people/sj26-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/sj26-small.jpg -------------------------------------------------------------------------------- /app/images/people/toolmantim.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/toolmantim.jpg -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/emojis"] 2 | path = vendor/emojis 3 | url = https://github.com/buildkite/emojis.git 4 | -------------------------------------------------------------------------------- /app/css/font-weights.css: -------------------------------------------------------------------------------- 1 | .thin{ font-weight: 200; } 2 | .light{ font-weight: 300; } 3 | .semi-bold{ font-weight: 500; } 4 | -------------------------------------------------------------------------------- /app/emoji/apple.js: -------------------------------------------------------------------------------- 1 | export default require("!!./../../webpack/emoji-loader!./../../vendor/emojis/img-apple-64.json"); 2 | -------------------------------------------------------------------------------- /app/images/people/justin-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/justin-small.jpg -------------------------------------------------------------------------------- /app/images/people/ticky-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/ticky-small.jpg -------------------------------------------------------------------------------- /app/components/shared/Icon/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/css/cursor.css: -------------------------------------------------------------------------------- 1 | .cursor-pointer { 2 | cursor: pointer; 3 | } 4 | 5 | .cursor-default { 6 | cursor: default; 7 | } 8 | -------------------------------------------------------------------------------- /app/emoji/buildkite.js: -------------------------------------------------------------------------------- 1 | export default require("!!./../../webpack/emoji-loader!./../../vendor/emojis/img-buildkite-64.json"); 2 | -------------------------------------------------------------------------------- /app/images/people/eleanor-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/eleanor-small.jpg -------------------------------------------------------------------------------- /app/images/people/harriet-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/harriet-small.jpg -------------------------------------------------------------------------------- /app/images/people/keithpitt-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/keithpitt-small.jpg -------------------------------------------------------------------------------- /app/images/people/matthew-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/matthew-small.jpg -------------------------------------------------------------------------------- /flow-typed/Features.js: -------------------------------------------------------------------------------- 1 | declare var Features: {| 2 | Widescreen: boolean, 3 | OrganizationBuildsPage: boolean 4 | |}; 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | tmp/* 2 | log/* 3 | Dockerfile 4 | docker-compose.yml 5 | **/.git 6 | node_modules 7 | dist 8 | buildkite-script-* 9 | -------------------------------------------------------------------------------- /app/images/people/toolmantim-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/frontend/HEAD/app/images/people/toolmantim-small.jpg -------------------------------------------------------------------------------- /app/css/interaction-events.css: -------------------------------------------------------------------------------- 1 | .user-select-none { 2 | user-select: none; 3 | } 4 | 5 | .pointer-events-none { 6 | pointer-events: none; 7 | } -------------------------------------------------------------------------------- /app/components/shared/Icon/down-triangle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/components/OrganizationShow/constants.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export const PIPELINES_INITIAL_PAGE_SIZE = 30; 4 | export const PIPELINES_PAGE_SIZE = 50; 5 | -------------------------------------------------------------------------------- /app/components/shared/Icon/menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.buildkite/steps/eslint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | echo "+++ :eslint: Running eslint" 5 | yarn run lint 6 | 7 | echo "👌 Looks good to me!" 8 | -------------------------------------------------------------------------------- /.buildkite/steps/flow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | echo "+++ :flowtype: Checking types" 5 | yarn run flow check 6 | 7 | echo "👌 All our types check out! 😉" 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Webpack 2 | dist 3 | 4 | # Jest Snapshots 5 | **/__snapshots__ 6 | 7 | # Flow Type Definitions 8 | flow-typed 9 | 10 | # Jest coverage output 11 | coverage 12 | -------------------------------------------------------------------------------- /app/queries/Viewer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | export const query = () => Relay.QL` 6 | query { 7 | viewer 8 | } 9 | `; 10 | -------------------------------------------------------------------------------- /app/components/shared/Icon/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/constants/TeamPrivacyConstants.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const TeamPrivacyConstants = { 4 | VISIBLE: "VISIBLE", 5 | SECRET: "SECRET" 6 | }; 7 | 8 | export default TeamPrivacyConstants; 9 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | # PORT=5700 2 | webpack: yarn run webpack-dev-server --no-progress 3 | 4 | # PORT=5800 (unused) 5 | relay: script/watch_graph 6 | 7 | # PORT=5900 8 | storybook: yarn storybook --quiet 9 | -------------------------------------------------------------------------------- /app/components/shared/Icon/permission-small-tick.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jest/setupTestFrameworkScriptFile.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const enzyme = require('enzyme'); 4 | const Adapter = require('enzyme-adapter-react-16'); 5 | 6 | enzyme.configure({ adapter: new Adapter() }); 7 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-a11y/register'; 3 | import '@storybook/addon-knobs/register'; 4 | import '@storybook/addon-storysource/register'; -------------------------------------------------------------------------------- /app/constants/TeamMemberRoleConstants.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const TeamMemberRoleConstants = { 4 | MAINTAINER: "MAINTAINER", 5 | MEMBER: "MEMBER" 6 | }; 7 | 8 | export default TeamMemberRoleConstants; 9 | -------------------------------------------------------------------------------- /app/css/shadows.css: -------------------------------------------------------------------------------- 1 | .shadow { 2 | box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3), 3 | 0 0 0 1px rgba(0, 0, 0, 0.03); 4 | } 5 | 6 | .shadow-subtle { 7 | box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); 8 | } -------------------------------------------------------------------------------- /app/css/letter-spacing.css: -------------------------------------------------------------------------------- 1 | .letter-spacing-0 { letter-spacing: 0; } 2 | .letter-spacing-1 { letter-spacing: .025em; } 3 | .letter-spacing-2 { letter-spacing: .5em; } 4 | .letter-spacing-3 { letter-spacing: .1em; } 5 | -------------------------------------------------------------------------------- /app/constants/OrganizationMemberRoleConstants.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const OrganizationMemberRoleConstants = { 4 | ADMIN: "ADMIN", 5 | MEMBER: "MEMBER" 6 | }; 7 | 8 | export default OrganizationMemberRoleConstants; 9 | -------------------------------------------------------------------------------- /app/queries/APIAccessTokenCode.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | export const query = () => Relay.QL` 6 | query { 7 | apiAccessTokenCode(code: $code) 8 | } 9 | `; 10 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-polyfill_v6.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 28eccd914ac7bd65de204cb1d8d37cfe 2 | // flow-typed version: 7b122e75af/babel-polyfill_v6.x.x/flow_>=v0.30.x 3 | 4 | declare module 'babel-polyfill' {} 5 | -------------------------------------------------------------------------------- /app/constants/OrganizationMemberSSOModeConstants.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const OrganizationMemberSSOModeConstants = { 4 | REQUIRED: "REQUIRED", 5 | OPTIONAL: "OPTIONAL" 6 | }; 7 | 8 | export default OrganizationMemberSSOModeConstants; 9 | -------------------------------------------------------------------------------- /app/components/shared/Icon/build-skipping.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /flow-typed/npm/flow-bin_v0.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583 2 | // flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x 3 | 4 | declare module "flow-bin" { 5 | declare module.exports: string; 6 | } 7 | -------------------------------------------------------------------------------- /app/constants/GraphQLErrors.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const GraphQLErrors = { 4 | ERROR: 'error', 5 | ESCALATION_ERROR: 'escalation_error', 6 | RECORD_VALIDATION_ERROR: 'record_validation_error' 7 | }; 8 | 9 | export default GraphQLErrors; 10 | -------------------------------------------------------------------------------- /app/components/shared/Icon/schedules.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/css/hover-fading.css: -------------------------------------------------------------------------------- 1 | .hover-faded, .hover-faded-children * { 2 | opacity: .75; 3 | } 4 | 5 | .hover-faded:hover, 6 | .hover-faded-children:hover *, 7 | .hover-faded-children:active *, 8 | .hover-faded-children:focus * { 9 | opacity: 1; 10 | } 11 | -------------------------------------------------------------------------------- /app/css/form.css: -------------------------------------------------------------------------------- 1 | /* If there are any invalid HTML5 elements in the form, automatically disable 2 | * the submit button */ 3 | form.form:invalid input[type=submit]:not([formnovalidate]) { 4 | pointer-events: none; 5 | opacity: 0.5; 6 | cursor: not-allowed; 7 | } 8 | -------------------------------------------------------------------------------- /app/css/radio.css: -------------------------------------------------------------------------------- 1 | /* This prevents a weird flicker when clicking Radio buttons in Safari... I 2 | * found this answer randomly on StackOverflow. No idea how/why it works... but 3 | * it does! #programming */ 4 | .radio { 5 | -webkit-transform: translateZ(0); 6 | } 7 | -------------------------------------------------------------------------------- /app/lib/relay/__mocks__/makeFetch.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export const MockFetch = jest.fn(); 4 | 5 | export default function MockMakeFetch(operation, variables, cacheConfig, uploadables) { 6 | return MockFetch(operation, variables, cacheConfig, uploadables); 7 | } 8 | -------------------------------------------------------------------------------- /flow-typed/npm/escape-html_v1.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a73e2d50cc06c99dd7dca35b500f9b27 2 | // flow-typed version: db85c4dbd2/escape-html_v1.x.x/flow_>=v0.25.x 3 | 4 | declare module "escape-html" { 5 | declare module.exports: (input: string) => string; 6 | } 7 | -------------------------------------------------------------------------------- /app/css/checkbox.css: -------------------------------------------------------------------------------- 1 | /* This prevents a weird flicker when clicking Radio buttons in Safari... I 2 | * found this answer randomly on StackOverflow. No idea how/why it works... but 3 | * it does! #programming */ 4 | .checkbox { 5 | -webkit-transform: translateZ(0); 6 | } 7 | -------------------------------------------------------------------------------- /app/css/emoji.css: -------------------------------------------------------------------------------- 1 | .emoji { 2 | width: 1.23em; 3 | height: 1.23em; 4 | margin-left:.05em; 5 | margin-right:.05em; 6 | vertical-align: -.2em; 7 | } 8 | 9 | .tiny-kitemoji .emoji { 10 | width: 1em; 11 | height: 1em; 12 | vertical-align: -.1em; 13 | } 14 | -------------------------------------------------------------------------------- /jest/fileTransformer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | process(src, filename, _config, _options) { 7 | return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';'; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /app/css/background-hover-colors.css: -------------------------------------------------------------------------------- 1 | .hover-bg-silver:hover { background-color: var(--silver) } 2 | .hover-bg-gray:hover { background-color: var(--gray) } 3 | .hover-bg-dark-gray:hover { background-color: var(--dark-gray) } 4 | .hover-bg-white:hover { background-color: white; } 5 | -------------------------------------------------------------------------------- /app/css/border-child.css: -------------------------------------------------------------------------------- 1 | .border-bottom-child > * { 2 | border-bottom: 1px solid transparent; 3 | } 4 | 5 | .border-bottom-child > *:last-child { 6 | border-bottom: 0; 7 | } 8 | 9 | .border-bottom-child-gray > * { 10 | border-bottom-color: var(--gray); 11 | } 12 | -------------------------------------------------------------------------------- /app/lib/words.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const VOWELS = 'aeiou'; 4 | 5 | export const indefiniteArticleFor = (word: string): string => { 6 | const first = ('' + word).toLowerCase()[0]; 7 | 8 | return VOWELS.indexOf(first) !== -1 9 | ? 'an' 10 | : 'a'; 11 | }; 12 | -------------------------------------------------------------------------------- /flow-typed/npm/create-react-class_v15.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 892fd8dcd3f17e76da4fb1334b0fd49e 2 | // flow-typed version: da30fe6876/create-react-class_v15.x.x/flow_>=v0.41.x 3 | 4 | declare module "create-react-class" { 5 | declare module.exports: React$CreateClass; 6 | } 7 | -------------------------------------------------------------------------------- /app/css/display.css: -------------------------------------------------------------------------------- 1 | @media (--breakpoint-sm) { 2 | .sm-block { display: block !important } 3 | } 4 | 5 | @media (--breakpoint-md) { 6 | .md-block { display: block !important } 7 | } 8 | 9 | @media (--breakpoint-lg) { 10 | .lg-block { display: block !important } 11 | } 12 | -------------------------------------------------------------------------------- /app/components/layout/Navigation/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /flow-typed/npm/object-assign_v4.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6b26bd45f602f11945a41846caafb9a1 2 | // flow-typed version: da30fe6876/object-assign_v4.x.x/flow_>=v0.25.x 3 | 4 | declare module "object-assign" { 5 | declare module.exports: (target: any, ...sources: Array) => Object; 6 | } 7 | -------------------------------------------------------------------------------- /app/components/shared/Icon/close.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/css/hover-underline.css: -------------------------------------------------------------------------------- 1 | .hover-underline:hover { 2 | text-decoration: underline; 3 | } 4 | 5 | .hover-underline-parent:hover .hover-underline-child { 6 | text-decoration: underline; 7 | } 8 | 9 | .hover-underline-dotted:hover { 10 | border-bottom: 1px dashed currentColor; 11 | } 12 | -------------------------------------------------------------------------------- /app/images/new-changelog-badge-bottom-corner.svg: -------------------------------------------------------------------------------- 1 | new-changelog-badge-bottom-corner -------------------------------------------------------------------------------- /app/lib/Bugsnag.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import Bugsnag from 'bugsnag-js'; 5 | import createPlugin from 'bugsnag-react'; 6 | 7 | const bugsnag = Bugsnag(window._bugsnag); 8 | 9 | export default bugsnag; 10 | 11 | export const ErrorBoundary = bugsnag.use(createPlugin(React)); 12 | -------------------------------------------------------------------------------- /app/lib/dasherize.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // dasherize("SomeStringTesting") will return some-string-testing 4 | export default function dasherize(string: ?string) { 5 | if (string) { 6 | return string.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").replace(/^-/g, "").replace(/-$/, ""); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /flow-typed/npm/es6-error_v4.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 59598aa3b00e126e674391832ba298ce 2 | // flow-typed version: da30fe6876/es6-error_v4.x.x/flow_>=v0.32.x 3 | 4 | declare module "es6-error" { 5 | declare class ExtendableError extends Error {} 6 | 7 | declare module.exports: Class; 8 | } 9 | -------------------------------------------------------------------------------- /stories/components/icons/Pipeline.stories.js: -------------------------------------------------------------------------------- 1 | /* global module */ 2 | 3 | import React from 'react'; 4 | import { storiesOf } from '@storybook/react'; 5 | 6 | import Pipeline from '../../../app/components/icons/Pipeline'; 7 | 8 | storiesOf('Icons', module) 9 | .add('Pipeline', () => ( 10 | 11 | )); -------------------------------------------------------------------------------- /app/components/shared/Icon/badges.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/components/shared/SectionLoader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Spinner from './Spinner'; 4 | 5 | export default class SectionLoader extends React.PureComponent { 6 | render() { 7 | return ( 8 |
9 | 10 |
11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/components/shared/Icon/permission-small-cross.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/components/shared/Icon/search.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/css/focus-colors.css: -------------------------------------------------------------------------------- 1 | .focus-green:focus { 2 | color: var(--green); 3 | } 4 | 5 | .focus-lime:focus { 6 | color: var(--lime); 7 | } 8 | 9 | .focus-blue:focus { 10 | color: var(--blue); 11 | } 12 | 13 | .focus-white:focus { 14 | color: var(--white) !important; 15 | } 16 | 17 | .focus-black:focus { 18 | color: var(--black); 19 | } 20 | -------------------------------------------------------------------------------- /app/components/shared/Icon/circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/constants/BuildStates.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const BuildStates = { 4 | SKIPPED: "SKIPPED", 5 | SCHEDULED: "SCHEDULED", 6 | RUNNING: "RUNNING", 7 | PASSED: "PASSED", 8 | FAILED: "FAILED", 9 | CANCELING: "CANCELING", 10 | CANCELED: "CANCELED", 11 | BLOCKED: "BLOCKED", 12 | NOT_RUN: "NOT_RUN" 13 | }; 14 | 15 | export default BuildStates; 16 | -------------------------------------------------------------------------------- /app/components/shared/TabControl/index.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import Tab from './Tab'; 4 | 5 | const TabControl = styled.ul.attrs({ 6 | className: 'flex m0 mb4 p0 border-bottom border-gray' 7 | })` 8 | list-style: none; 9 | list-style-type: none; 10 | `; 11 | 12 | TabControl.Tab = Tab; 13 | 14 | export default TabControl; 15 | -------------------------------------------------------------------------------- /app/components/shared/Autocomplete/loader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Spinner from 'app/components/shared/Spinner'; 4 | 5 | export default class Loader extends React.PureComponent { 6 | static displayName = "Autocomplete.Loader"; 7 | 8 | render() { 9 | return ( 10 |
  • 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/css/fonts.css: -------------------------------------------------------------------------------- 1 | .system { 2 | font-family: var(--font-family-system); 3 | } 4 | 5 | .monospace { 6 | font-family: var(--font-family-mono); 7 | } 8 | 9 | .tabular-numerals { 10 | /* Enables OpenType tabular numerals */ 11 | font-feature-settings: "tnum"; /* not the "correct" property, but it works in IE10+ */ 12 | font-variant-numeric: tabular-nums; 13 | } 14 | -------------------------------------------------------------------------------- /app/components/shared/PageWithContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default class PageWithContainer extends React.PureComponent { 5 | static propTypes = { 6 | children: PropTypes.node.isRequired 7 | }; 8 | 9 | render() { 10 | return ( 11 |
    {this.props.children}
    12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/lib/ValidationErrors.js: -------------------------------------------------------------------------------- 1 | export default class ValidationErrors { 2 | constructor(errors) { 3 | this.errors = errors; 4 | } 5 | 6 | findForField(field) { 7 | if (this.errors && this.errors.length > 0) { 8 | return this.errors 9 | .filter((error) => error.field === field) 10 | .map((error) => error.message); 11 | } 12 | 13 | return []; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.buildkite/steps/jest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | echo "+++ :jest: Running Jest" 5 | yarn run test-with-coverage 6 | 7 | echo "👌 Looks good to me!" 8 | 9 | echo "--- :compression: Packaging coverage report" 10 | tar -c -v -z -f "coverage/lcov-report-${BUILDKITE_ORGANIZATION_SLUG}-${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_COMMIT}.tgz" -C "coverage/lcov-report" "." 11 | 12 | echo "📑 Done!" 13 | -------------------------------------------------------------------------------- /app/components/shared/FormYAMLEditorField/codemirror.js: -------------------------------------------------------------------------------- 1 | export default from 'codemirror'; 2 | 3 | import 'app/css/codemirror.css'; 4 | 5 | import 'codemirror/addon/hint/show-hint'; 6 | import 'codemirror/addon/comment/comment'; 7 | import 'codemirror/addon/edit/matchbrackets'; 8 | import 'codemirror/addon/edit/closebrackets'; 9 | import 'codemirror/keymap/sublime'; 10 | import 'codemirror/mode/yaml/yaml'; 11 | -------------------------------------------------------------------------------- /app/css/svg-colors.css: -------------------------------------------------------------------------------- 1 | /* 2 | Classes to use to set SVG color properties 3 | 4 | Create them as you need. 5 | */ 6 | 7 | .stroke-black { stroke: var(--black) } 8 | .stroke-gray { stroke: var(--gray) } 9 | .stroke-dark-gray { stroke: var(--dark-gray) } 10 | .stroke-silver { stroke: var(--silver) } 11 | .stroke-white { stroke: var(--white) } 12 | .stroke-lime { stroke: var(--lime) } 13 | -------------------------------------------------------------------------------- /app/queries/Organization.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | // Note: Ensure whatever variable you use as the $slug is unique and doesn't 6 | // match any existing variables in any other queries otherwise React Relay 7 | // Router doesn't work very well. 8 | 9 | export const query = () => Relay.QL` 10 | query { 11 | organization(slug: $organization) 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /app/components/shared/__snapshots__/BuildStatusDescription.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`BuildStatusDescription calls through to \`getRelativeDateString\` and \`buildStatus\` 1`] = ` 4 | 5 | tested 6 | 7 | 13 | 14 | `; 15 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | services: 4 | frontend: 5 | build: . 6 | environment: 7 | - EMOJI_HOST 8 | - BUILDKITE 9 | - BUILDKITE_COMMIT 10 | - BUILDKITE_ORGANIZATION_SLUG 11 | - BUILDKITE_PIPELINE_SLUG 12 | - CI 13 | volumes: 14 | - "./bundle-analysis:/frontend/bundle-analysis" 15 | - "./coverage:/frontend/coverage" 16 | - "./dist:/host/dist" -------------------------------------------------------------------------------- /app/components/shared/Icon/queues.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/components/user/graphql/GraphQLExplorerDocumentation/Scalar.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react"; 4 | 5 | type Props = { 6 | name: string 7 | }; 8 | 9 | export default class Scalar extends React.PureComponent { 10 | render() { 11 | return ( 12 | 13 | {this.props.name} 14 | 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/components/user/graphql/GraphQLExplorerDocumentation/Argument.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react"; 4 | 5 | type Props = { 6 | name: string 7 | }; 8 | 9 | export default class Argument extends React.PureComponent { 10 | render() { 11 | return ( 12 | 13 | {this.props.name} 14 | 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10-stretch 2 | 3 | EXPOSE 4890 4 | 5 | ENV EMOJI_HOST=http://buildkite.localhost/_frontend/vendor/emojis 6 | 7 | WORKDIR /frontend 8 | 9 | # Install yarn dependencies 10 | ADD package.json yarn.lock /frontend/ 11 | RUN yarn install 12 | 13 | # Add the soure code to the image and check it builds 14 | ADD . /frontend/ 15 | RUN yarn build 16 | 17 | # Serve via webpack-dev-server 18 | CMD ["yarn", "run", "webpack-dev-server"] 19 | -------------------------------------------------------------------------------- /jest/browserMocks.js: -------------------------------------------------------------------------------- 1 | class LocalStorageMock { 2 | constructor() { 3 | this.store = {}; 4 | } 5 | 6 | clear() { 7 | this.store = {}; 8 | } 9 | 10 | getItem(key) { 11 | return this.store[key] || null; 12 | } 13 | 14 | setItem(key, value) { 15 | this.store[key] = value.toString(); 16 | } 17 | 18 | removeItem(key) { 19 | delete this.store[key]; 20 | } 21 | } 22 | 23 | window.localStorage = new LocalStorageMock; 24 | -------------------------------------------------------------------------------- /jest/schemaMocks/addMockFunctionsToSchema.js: -------------------------------------------------------------------------------- 1 | // @flow weak 2 | 3 | import { addMockFunctionsToSchema } from 'graphql-tools'; 4 | import DefaultMocks from './DefaultMocks'; 5 | 6 | export default function(schema, mocks) { 7 | addMockFunctionsToSchema({ 8 | schema, 9 | mocks: { 10 | ID: DefaultMocks.ID, 11 | String: DefaultMocks.String, 12 | DateTime: DefaultMocks.DateTime, 13 | 14 | ...mocks 15 | } 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /app/lib/jobCommandOneliner.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // Reformats a multi-line job command into a single line bash command. Returns 4 | // falsey if command is falsey. 5 | // 6 | // For example: 7 | // jobCommandOneliner("\n\n\nls -l\n\necho 'oh hai'\n") 8 | // => "ls -l && echo 'oh hai'" 9 | export default function jobCommandOneliner(command: ?string): ?string { 10 | if (command) { 11 | return command.trim().replace(/\s*\n+\s*/g, " && "); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/css/scrollbar.css: -------------------------------------------------------------------------------- 1 | .scrollbar::-webkit-scrollbar { 2 | -webkit-appearance: none; 3 | } 4 | 5 | .scrollbar::-webkit-scrollbar:vertical { 6 | width: 11px; 7 | } 8 | 9 | .scrollbar::-webkit-scrollbar:horizontal { 10 | height: 11px; 11 | } 12 | 13 | .scrollbar::-webkit-scrollbar-thumb { 14 | border-radius: 8px; 15 | border: 2px solid white; /* should match background, can't be transparent */ 16 | background-color: rgba(0, 0, 0, .5); 17 | } 18 | -------------------------------------------------------------------------------- /app/components/OrganizationShow/Pipeline/constants.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export const MAXIMUM_NUMBER_OF_BUILDS = 30; 4 | export const BAR_HEIGHT_MINIMUM = 3; 5 | export const BAR_WIDTH = 7; 6 | export const BAR_SEPERATOR_WIDTH = 1; 7 | export const BAR_WIDTH_WITH_SEPERATOR = BAR_WIDTH + BAR_SEPERATOR_WIDTH; 8 | export const GRAPH_HEIGHT = 35; 9 | export const GRAPH_WIDTH = (BAR_WIDTH * MAXIMUM_NUMBER_OF_BUILDS) + ((MAXIMUM_NUMBER_OF_BUILDS * BAR_SEPERATOR_WIDTH) - 1); 10 | -------------------------------------------------------------------------------- /app/components/audit_log/Drawer/shared.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import styled from 'styled-components'; 4 | 5 | //
    is inline-block with `width: 100%` 6 | // to prevent CSS columns from breaking inside 7 | export const Section = styled.section.attrs({ 8 | className: 'mb4 inline-block' 9 | })` 10 | width: 100%; 11 | `; 12 | 13 | export const SectionHeading = styled.h3` 14 | font-size: 1em; 15 | font-weight: 500; 16 | text-transform: uppercase; 17 | `; 18 | -------------------------------------------------------------------------------- /app/components/shared/Icon/sso.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/lib/commits.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export function shortMessage(message: ?string): string { 4 | if (message) { 5 | return message.split('\n')[0]; 6 | } 7 | 8 | return ''; 9 | } 10 | 11 | export function shortCommit(commitish: string, length: number = 7): string { 12 | // Does this look like a git sha? 13 | if (commitish && commitish.length === 40 && !commitish.match(/[^a-f0-9]/i)) { 14 | return commitish.substring(0, length); 15 | } 16 | 17 | return commitish; 18 | } 19 | -------------------------------------------------------------------------------- /stories/shared/Spinner.stories.js: -------------------------------------------------------------------------------- 1 | /* global module */ 2 | 3 | import React from 'react'; 4 | import { storiesOf } from '@storybook/react'; 5 | import { boolean, number } from '@storybook/addon-knobs'; 6 | 7 | import Spinner from '../../app/components/shared/Spinner'; 8 | 9 | storiesOf('Spinner', module) 10 | .add('Standard', () => ) 11 | .add('Mono', () => ); -------------------------------------------------------------------------------- /app/components/layout/Footer/link.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default class Link extends React.PureComponent { 5 | static displayName = "Footer.Link"; 6 | 7 | static propTypes = { 8 | href: PropTypes.string.isRequired, 9 | children: PropTypes.node.isRequired 10 | }; 11 | 12 | render() { 13 | return ( 14 | {this.props.children} 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/components/shared/PermissionSelectOptionDescriptions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default class PermissionSelectOptionDescriptions extends React.PureComponent { 5 | static propTypes = { 6 | children: PropTypes.node.isRequired 7 | }; 8 | 9 | render() { 10 | return ( 11 |
    12 | {this.props.children} 13 |
    14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/lib/relay/makeFetch.js: -------------------------------------------------------------------------------- 1 | // @flow weak 2 | 3 | export default function makeFetch(operation, variables) { 4 | return fetch(window._graphql.url, { 5 | method: 'POST', 6 | headers: { 7 | ...window._graphql.headers, 8 | 'Accept': 'application/json', 9 | 'Content-Type': 'application/json' 10 | }, 11 | credentials: 'same-origin', 12 | body: JSON.stringify({ 13 | query: operation.text, 14 | variables 15 | }) 16 | }).then((response) => response.json()); 17 | } 18 | -------------------------------------------------------------------------------- /app/components/shared/Menu/header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default class Header extends React.PureComponent { 5 | static displayName = "Menu.Header"; 6 | 7 | static propTypes = { 8 | children: PropTypes.node.isRequired 9 | }; 10 | 11 | render() { 12 | return ( 13 |
    14 | {this.props.children} 15 |
    16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/components/user/graphql/GraphQLExplorerDocumentation/Comment.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react"; 4 | import wrap from "word-wrap"; 5 | 6 | type Props = { 7 | text: string 8 | }; 9 | 10 | export default class Comment extends React.PureComponent { 11 | render() { 12 | return ( 13 |
    14 | {wrap(this.props.text || "n/a", { width: 70, indent: '' }).replace(/(^|\n)/g, "$1# ")} 15 |
    16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/lib/warn.js: -------------------------------------------------------------------------------- 1 | // @flow weak 2 | 3 | /* eslint-disable no-unused-vars */ 4 | let warn = (...args) => {}; 5 | 6 | if (process.env.NODE_ENV !== "production") { 7 | warn = (condition: boolean, format: string, ...args) => { 8 | if (!condition) { 9 | const name = "Warning:"; 10 | let argIndex = 0; 11 | const message = format.replace(/%s/g, () => (args[argIndex++])); 12 | /* eslint-disable no-console */ 13 | console.error(name, message); 14 | } 15 | }; 16 | } 17 | 18 | export default warn; 19 | -------------------------------------------------------------------------------- /app/lib/reactRenderer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /* eslint-disable react/no-render-return-value */ 3 | 4 | import * as React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | import { ErrorBoundary } from './Bugsnag'; 7 | 8 | export default function reactRenderer( 9 | element: React$Element, 10 | container: Element, 11 | callback?: () => void 12 | ) { 13 | return ReactDOM.render( 14 | {element}, 15 | container, 16 | callback 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /flow-typed/npm/deepmerge_v2.1.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: cf8f173b269ecc9a9ae029395afce17b 2 | // flow-typed version: e6922b8125/deepmerge_v2.1.x/flow_>=v0.57.3 3 | 4 | declare module 'deepmerge' { 5 | declare type Options = { 6 | clone?: boolean, 7 | arrayMerge?: (destination: any[], source: any[], options?: Options) => Array 8 | } 9 | 10 | declare module.exports: { 11 | (a: A, b: B, options?: Options): A & B, 12 | all(objects: Array<$Shape>, options?: Options): T 13 | }; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | # This JSON file is invalid and breaks flow with an "Unexpected string" error. 3 | .*/node_modules/config-chain/test/broken.json 4 | # Ignore jest mocks 5 | .*/__mocks__/.* 6 | 7 | [include] 8 | 9 | [libs] 10 | 11 | [lints] 12 | all=warn 13 | 14 | [options] 15 | emoji=true 16 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe 17 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectError 18 | module.use_strict=true 19 | module.ignore_non_literal_requires=true 20 | module.name_mapper='^app/\(.*\)$' -> '/app/\1' 21 | -------------------------------------------------------------------------------- /app/css/btn-outline.css: -------------------------------------------------------------------------------- 1 | .btn-outline { 2 | border-radius: 3px; 3 | } 4 | 5 | .btn-outline:hover { 6 | box-shadow: inset 0 0 0 20rem var(--darken-1); 7 | } 8 | 9 | .btn-outline:focus { 10 | border-color: var(--darken-2); 11 | } 12 | 13 | .btn-outline:active { 14 | outline: 0; 15 | box-shadow: inset 0 0 0 10rem var(--darken-2), 16 | inset 0 3px 4px 0 var(--darken-1), 17 | 0 0 1px var(--darken-1); 18 | } 19 | 20 | .btn-outline:disabled, 21 | .btn-outline.is-disabled { 22 | opacity: .5; 23 | cursor: not-allowed; 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ingore custom .env file 2 | .env 3 | 4 | # OSX cache files 5 | .DS_Store 6 | 7 | # git head commit sha without .git 8 | /REVISION 9 | 10 | # Node 11 | node_modules 12 | npm-debug.log 13 | 14 | # Webpack 15 | dist 16 | 17 | # Temp folders 18 | tmp 19 | 20 | # Jest coverage output 21 | coverage 22 | 23 | # Webpack bundle analysis 24 | bundle-analysis 25 | 26 | # Babel generated files (from relay-compiler) 27 | __generated__ 28 | 29 | # Storybook exports generated using `yarn build-storybook` 30 | storybook-static 31 | 32 | .cache/ -------------------------------------------------------------------------------- /app/components/shared/FormDataList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | class FormDataList extends React.PureComponent { 5 | static propTypes = { 6 | id: PropTypes.node.isRequired, 7 | values: PropTypes.arrayOf(PropTypes.string.isRequired) 8 | }; 9 | 10 | render() { 11 | return ( 12 | 13 | {this.props.values.map((value) => 15 | ); 16 | } 17 | } 18 | 19 | export default FormDataList; 20 | -------------------------------------------------------------------------------- /app/lib/number.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import window from 'global/window'; 4 | 5 | // Formats numbers nicely based on their current locale 6 | // e.g. 4200000 -> 4,200,000 7 | export const formatNumber = ( 8 | (window.Intl && window.Intl.NumberFormat) 9 | ? ((formatter, number: number): string => ( 10 | formatter.format(number) 11 | )).bind(this, window.Intl.NumberFormat()) 12 | : (number: number): string => ( 13 | number.toLocaleString 14 | ? number.toLocaleString() 15 | : number.toString() 16 | ) 17 | ); 18 | -------------------------------------------------------------------------------- /flow-typed/npm/react-addons-perf_v15.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 331b4c1d398890147570f4ea0fe0ec7a 2 | // flow-typed version: b43dff3e0e/react-addons-perf_v15.x.x/flow_>=v0.16.x 3 | 4 | declare module 'react-addons-perf' { 5 | declare function start(): void; 6 | declare function stop(): void; 7 | declare function printWasted(): void; 8 | declare function getLastMeasurements(): mixed; 9 | declare function printInclusive(): void; 10 | declare function printExclusive(): void; 11 | declare function printOperations(): void; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /app/components/shared/BetaBadge.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import * as React from 'react'; 4 | import Badge from 'app/components/shared/Badge'; 5 | 6 | type Props = { 7 | forumTopicUrl: string 8 | }; 9 | 10 | export default class BetaBadge extends React.PureComponent { 11 | render() { 12 | return ( 13 | 14 | 15 | Beta 16 | 17 | 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/components/shared/PageHeader/button.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import BaseButton from 'app/components/shared/Button'; 5 | 6 | export default class Button extends React.PureComponent { 7 | static displayName = "PageHeader.Button"; 8 | 9 | static propTypes = { 10 | children: PropTypes.node.isRequired 11 | }; 12 | 13 | render() { 14 | return ( 15 | {this.props.children} 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /jest/schemaMocks/DefaultMocks.js: -------------------------------------------------------------------------------- 1 | // @flow weak 2 | 3 | export default class DefaultMocks { 4 | static get ID() { 5 | const ids = new Map(); 6 | 7 | return (_parent, _args, _context, { parentType }) => { 8 | const nextId = (ids.get(parentType) + 1 || 1); 9 | ids.set(parentType, nextId); 10 | return `ID:${parentType}:${nextId}`; 11 | }; 12 | } 13 | 14 | static get String() { 15 | return () => ""; 16 | } 17 | 18 | static get DateTime() { 19 | return () => new Date(1986, 7, 28).valueOf().toString(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/css/text.css: -------------------------------------------------------------------------------- 1 | .small { 2 | font-size: 85%; 3 | } 4 | 5 | .underline-dotted { 6 | border-bottom: 1px dashed currentColor; 7 | } 8 | 9 | .overflow-ellipsis { 10 | text-overflow: ellipsis; 11 | } 12 | 13 | .wrap-break-word { 14 | word-wrap: break-word; 15 | } 16 | 17 | @media (--breakpoint-sm) { 18 | .sm-right-align { text-align: right !important } 19 | } 20 | 21 | @media (--breakpoint-md) { 22 | .md-right-align { text-align: right !important } 23 | } 24 | 25 | @media (--breakpoint-lg) { 26 | .lg-right-align { text-align: right !important } 27 | } 28 | -------------------------------------------------------------------------------- /app/lib/repositories.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export function repositoryProviderIcon(providerName: ?string): string { 4 | switch (providerName) { 5 | case 'RepositoryProviderBitbucket': 6 | return 'bitbucket'; 7 | case 'RepositoryProviderGithub': 8 | return 'github'; 9 | case 'RepositoryProviderGithubEnterprise': 10 | return 'github'; 11 | case 'RepositoryProviderGitlab': 12 | return 'gitlab'; 13 | case 'RepositoryProviderGitlabCommunity': 14 | return 'gitlab'; 15 | default: 16 | return 'git'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/queries/Team.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | // Note: Ensure whatever variable you use as the $slug is unique and doesn't 6 | // match any existing variables in any other queries otherwise React Relay 7 | // Router doesn't work very well. 8 | 9 | export const query = () => Relay.QL` 10 | query { 11 | team(slug: $teamSlug) 12 | } 13 | `; 14 | 15 | export const prepareParams = (params: Object) => { 16 | return { 17 | ...params, 18 | teamSlug: [params.organization, params.team].join("/") 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /html-sketchapp.config.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export default { 4 | viewports: { 5 | Desktop: '1024x768', 6 | Mobile: '320x568' 7 | }, 8 | symbolLayerMiddleware: (args: *) => { 9 | const { layer, SVG, RESIZING_CONSTRAINTS } = args; 10 | 11 | if (layer instanceof SVG) { 12 | layer.setResizingConstraint(RESIZING_CONSTRAINTS.TOP, RESIZING_CONSTRAINTS.LEFT, RESIZING_CONSTRAINTS.WIDTH, RESIZING_CONSTRAINTS.HEIGHT); 13 | } else { 14 | layer.setResizingConstraint(RESIZING_CONSTRAINTS.LEFT, RESIZING_CONSTRAINTS.TOP); 15 | } 16 | } 17 | }; -------------------------------------------------------------------------------- /app/components/layout/Navigation/nav-button-right-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/public-path.js: -------------------------------------------------------------------------------- 1 | /* global __webpack_public_path__:true */ 2 | /* exported __webpack_public_path__ */ 3 | 4 | // Allow specifying the webpack public path 5 | // 6 | // When running webpack dev server in development it provides a public path, 7 | // and we should use it. 8 | // 9 | // Must be done in a module so that it is executed before all other imports. 10 | // 11 | // See https://webpack.js.org/guides/public-path/#on-the-fly 12 | if (__webpack_public_path__ === "" && window._frontendPublicPath) { 13 | __webpack_public_path__ = window._frontendPublicPath; 14 | } 15 | -------------------------------------------------------------------------------- /app/queries/Agent.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | // Note: Ensure whatever variable you use as the $slug is unique and doesn't 6 | // match any existing variables in any other queries otherwise React Relay 7 | // Router doesn't work very well. 8 | 9 | export const query = () => Relay.QL` 10 | query { 11 | agent(slug: $agentSlug) 12 | } 13 | `; 14 | 15 | export const prepareParams = (params: Object) => { 16 | return { 17 | ...params, 18 | agentSlug: [params.organization, params.agent].join("/") 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /stories/shared/FormYamlEditorField.stories.js: -------------------------------------------------------------------------------- 1 | /* global module */ 2 | 3 | import React from 'react'; 4 | import { storiesOf } from '@storybook/react'; 5 | 6 | import FormYAMLEditorField from '../../app/components/shared/FormYAMLEditorField'; 7 | 8 | const exampleYaml = `steps: 9 | - label: ':yarn:' 10 | command: 'yarn test' 11 | - label: ':dust:' 12 | command: 'yarn lint' 13 | - wait 14 | - trigger: 'deploy'`; 15 | 16 | storiesOf('FormatYAMLEditorField', module) 17 | .add('Index', () => ( 18 | 19 | )); -------------------------------------------------------------------------------- /app/components/shared/PipelineStatus/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import * as React from 'react'; 4 | import Badge from 'app/components/shared/Badge'; 5 | 6 | type Props = { 7 | public: boolean 8 | }; 9 | 10 | export default class PipelineStatus extends React.PureComponent { 11 | render() { 12 | if (this.props.public) { 13 | return ( 14 |
    15 | Public 16 |
    17 | ); 18 | } 19 | 20 | return null; 21 | } 22 | } -------------------------------------------------------------------------------- /app/queries/Pipeline.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | // Note: Ensure whatever variable you use as the $slug is unique and doesn't 6 | // match any existing variables in any other queries otherwise React Relay 7 | // Router doesn't work very well. 8 | 9 | export const query = () => Relay.QL` 10 | query { 11 | pipeline(slug: $pipelineSlug) 12 | } 13 | `; 14 | 15 | export const prepareParams = (params: Object) => { 16 | return { 17 | ...params, 18 | pipelineSlug: [params.organization, params.pipeline].join("/") 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /app/components/shared/PageHeader/title.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | class Title extends React.PureComponent { 6 | static displayName = "PageHeader.Title"; 7 | 8 | static propTypes = { 9 | children: PropTypes.node.isRequired, 10 | className: PropTypes.string 11 | }; 12 | 13 | render() { 14 | return ( 15 |

    16 | {this.props.children} 17 |

    18 | ); 19 | } 20 | } 21 | 22 | export default Title; 23 | -------------------------------------------------------------------------------- /app/components/shared/FormTextField.js: -------------------------------------------------------------------------------- 1 | import collapsible from './collapsibleFormComponent'; 2 | import labelled from './labelledFormComponent'; 3 | 4 | const textFieldDefaultProps = { type: 'text' }; 5 | 6 | const FormTextField = labelled('input'); 7 | FormTextField.defaultProps = { 8 | ...FormTextField.defaultProps, 9 | ...textFieldDefaultProps 10 | }; 11 | 12 | FormTextField.Collapsible = collapsible('input'); 13 | FormTextField.Collapsible.defaultProps = { 14 | ...FormTextField.Collapsible.defaultProps, 15 | ...textFieldDefaultProps 16 | }; 17 | 18 | export default FormTextField; 19 | -------------------------------------------------------------------------------- /app/components/shared/Icon/pipeline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/components/shared/Icon/plus-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/components/shared/Icon/github.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/components/shared/PageHeader/menu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | export default class Menu extends React.PureComponent { 6 | static displayName = 'PageHeader.Menu'; 7 | static propTypes = { 8 | children: PropTypes.node.isRequired, 9 | className: PropTypes.string 10 | }; 11 | 12 | render() { 13 | const { className, children } = this.props; 14 | 15 | return ( 16 |
    17 | {children} 18 |
    19 | ); 20 | } 21 | } -------------------------------------------------------------------------------- /app/components/user/TwoFactor/TwoFactorConfigure/TwoFactorConfigureActivate/buildkite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/components/docs/07-windows.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Windows 3 | --- 4 | 1. Download the latest Windows beta from [Buildkite Agent releases on GitHub](https://github.com/buildkite/agent/releases) 5 | 2. Extract the files to a directory of your choice 6 | 3. Edit `buildkite-agent.cfg` and add your token 7 | 4. Run `buildkite-agent start` from a command prompt 8 | 9 |

    See the Windows agent docs for more details.

    10 | 11 | When asked, enter your agent token: 12 | 13 | ```markdown 14 | {{ props.token || 'INSERT-YOUR-AGENT-TOKEN-HERE' }} 15 | ``` 16 | -------------------------------------------------------------------------------- /app/components/shared/FormInputHelp.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | const FormInputHelp = ({ className, children, ...props }) => { 6 | if (!children) { 7 | return null; 8 | } 9 | 10 | return ( 11 |

    15 | {children} 16 |

    17 | ); 18 | }; 19 | 20 | FormInputHelp.propTypes = { 21 | className: PropTypes.string, 22 | children: PropTypes.node 23 | }; 24 | 25 | export default FormInputHelp; 26 | -------------------------------------------------------------------------------- /app/components/shared/FormTextarea.js: -------------------------------------------------------------------------------- 1 | import AutosizingTextarea from './AutosizingTextarea'; 2 | import collapsible from './collapsibleFormComponent'; 3 | import labelled from './labelledFormComponent'; 4 | 5 | const FormTextarea = labelled('textarea'); 6 | FormTextarea.Autosize = labelled(AutosizingTextarea); 7 | FormTextarea.Autosize.proxyMethods = ['updateAutoresize']; 8 | 9 | FormTextarea.Collapsible = collapsible('textarea'); 10 | FormTextarea.Collapsible.Autosize = collapsible(AutosizingTextarea); 11 | FormTextarea.Collapsible.Autosize.proxyMethods = ['updateAutoresize']; 12 | 13 | export default FormTextarea; 14 | -------------------------------------------------------------------------------- /app/components/shared/Autocomplete/error-message.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | export default class ErrorMessage extends React.PureComponent { 6 | static displayName = "Autocomplete.ErrorMessage"; 7 | 8 | static propTypes = { 9 | children: PropTypes.node.isRequired, 10 | className: PropTypes.string 11 | }; 12 | 13 | render() { 14 | const classes = classNames(this.props.className, "px2 py2 dark-gray"); 15 | 16 | return ( 17 |
  • {this.props.children}
  • 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /flow-typed/npm/fetch-jsonp_v1.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 3b3fd8f4b622097c9b036f8ba70327fd 2 | // flow-typed version: c0fddcdf0c/fetch-jsonp_v1.x.x/flow_>=v0.38.x 3 | 4 | // Adapted from https://github.com/camsong/fetch-jsonp/blob/master/index.d.ts 5 | 6 | declare module "fetch-jsonp" { 7 | declare module.exports: (url: string, options?: Options) => Promise; 8 | 9 | declare type Options = { 10 | timeout?: number, 11 | jsonpCallback?: string, 12 | jsonpCallbackFunction?: string 13 | }; 14 | 15 | declare class Response { 16 | json(): Promise, 17 | ok: boolean 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/components/build/CommentsList.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import Relay from 'react-relay/classic'; 5 | 6 | class CommentsList extends React.PureComponent<{}> { 7 | render() { 8 | return ( 9 | Comments 10 | ); 11 | } 12 | } 13 | 14 | export default Relay.createContainer(CommentsList, { 15 | fragments: { 16 | viewer: () => Relay.QL` 17 | fragment on Viewer { 18 | user { 19 | name 20 | } 21 | } 22 | `, 23 | build: () => Relay.QL` 24 | fragment on Build { 25 | id 26 | } 27 | ` 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /app/components/docs/06-macos.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: macOS 3 | emoji: ':finder:' 4 | --- 5 | If you have [Homebrew](http://brew.sh/) installed you can use our [Buildkite formula repository](https://github.com/buildkite/homebrew-buildkite) to install the agent: 6 | 7 | ```bash 8 | brew tap buildkite/buildkite 9 | brew install --token='{{ props.token || 'INSERT-YOUR-AGENT-TOKEN-HERE' }}' buildkite-agent 10 | ``` 11 | 12 | If you don't use Homebrew you should follow the [Linux](/docs/agent/linux) install instructions. 13 | 14 |

    See the macOS agent docs for more details.

    15 | -------------------------------------------------------------------------------- /app/queries/PipelineSchedule.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | // Note: Ensure whatever variable you use as the $slug is unique and doesn't 6 | // match any existing variables in any other queries otherwise React Relay 7 | // Router doesn't work very well. 8 | 9 | export const query = () => Relay.QL` 10 | query { 11 | pipelineSchedule(slug: $pipelineScheduleSlug) 12 | } 13 | `; 14 | 15 | export const prepareParams = (params: Object) => { 16 | return { 17 | ...params, 18 | pipelineScheduleSlug: [params.organization, params.pipeline, params.schedule].join("/") 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /app/queries/OrganizationMember.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | // Note: Ensure whatever variable you use as the $slug is unique and doesn't 6 | // match any existing variables in any other queries otherwise React Relay 7 | // Router doesn't work very well. 8 | 9 | export const query = () => Relay.QL` 10 | query { 11 | organizationMember(slug: $organizationMemberSlug) 12 | } 13 | `; 14 | 15 | export const prepareParams = (params: Object) => { 16 | return { 17 | ...params, 18 | organizationMemberSlug: [params.organization, params.organizationMember].join("/") 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /app/components/shared/PageHeader/description.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | export default class Description extends React.PureComponent { 6 | static displayName = 'PageHeader.Description'; 7 | static propTypes = { 8 | children: PropTypes.node.isRequired, 9 | className: PropTypes.string 10 | }; 11 | 12 | render() { 13 | const { className, children } = this.props; 14 | 15 | return ( 16 |
    17 | {children} 18 |
    19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/constants/JobStates.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const JobStates = { 4 | PENDING: "PENDING", 5 | WAITING: "WAITING", 6 | WAITING_FAILED: "WAITING_FAILED", 7 | BLOCKED: "BLOCKED", 8 | BLOCKED_FAILED: "BLOCKED_FAILED", 9 | UNBLOCKED: "UNBLOCKED", 10 | UNBLOCKED_FAILED: "UNBLOCKED_FAILED", 11 | SCHEDULED: "SCHEDULED", 12 | ASSIGNED: "ASSIGNED", 13 | ACCEPTED: "ACCEPTED", 14 | RUNNING: "RUNNING", 15 | FINISHED: "FINISHED", 16 | CANCELING: "CANCELING", 17 | CANCELED: "CANCELED", 18 | TIMING_OUT: "TIMING_OUT", 19 | TIMED_OUT: "TIMED_OUT", 20 | SKIPPED: "SKIPPED", 21 | BROKEN: "BROKEN" 22 | }; 23 | 24 | export default JobStates; 25 | -------------------------------------------------------------------------------- /app/components/shared/Panel/header.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import classNames from 'classnames'; 4 | import PropTypes from 'prop-types'; 5 | import React from 'react'; 6 | 7 | type Props = { 8 | children: React$Node, 9 | className?: string 10 | }; 11 | 12 | export default class Header extends React.PureComponent { 13 | static propTypes = { 14 | children: PropTypes.node.isRequired, 15 | className: PropTypes.string 16 | }; 17 | 18 | render() { 19 | return ( 20 |

    21 | {this.props.children} 22 |

    23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.buildkite/steps/webpack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | mkdir -p bundle-analysis dist 5 | 6 | # Remove anything already in dist. The Dockerfile builds the assets already, 7 | # but not the production versions, so paths like app.js exist, and we don't 8 | # want to deploy those to production. 9 | rm dist/* 10 | 11 | echo "--- :webpack: Building Webpack assets for production, and analysing bundle" 12 | GENERATE_BUNDLE_REPORT=true yarn run build-production 13 | 14 | echo "--- :javascript: Checking valid JS" 15 | node --check dist/*.js && echo "👍 Javascript looks valid!" 16 | 17 | echo "--- :docker: Copying to the host for artifact upload" 18 | cp -a dist/* /host/dist 19 | -------------------------------------------------------------------------------- /app/components/shared/Icon/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/css/reset.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | /** 7 | * Prefer system fonts (ala -apple-system-body) 8 | * Mac/iOS - SF 9 | * Chromebook/Android - Roboto 10 | * Windows - Helvetica 11 | * Linux - Helvetica, Arial 12 | **/ 13 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Helvetica, sans-serif; 14 | font-size: 14px; 15 | line-height: 1.42857143; 16 | color: #333; 17 | margin: 0; 18 | } 19 | 20 | h1, h2, h3, h4, h5, h6 { 21 | line-height: 1.1; 22 | font-weight: 500; 23 | } 24 | 25 | pre { 26 | margin: 0; 27 | padding: 0; 28 | } 29 | 30 | table { 31 | border-collapse: collapse; 32 | } -------------------------------------------------------------------------------- /app/images/up-pointing-white-nib.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /flow-typed/npm/classnames_v2.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: cf86673cc32d185bdab1d2ea90578d37 2 | // flow-typed version: 614bf49aa8/classnames_v2.x.x/flow_>=v0.25.x 3 | 4 | type $npm$classnames$Classes = 5 | | string 6 | | { [className: string]: * } 7 | | false 8 | | void 9 | | null; 10 | 11 | declare module "classnames" { 12 | declare module.exports: ( 13 | ...classes: Array<$npm$classnames$Classes | $npm$classnames$Classes[]> 14 | ) => string; 15 | } 16 | 17 | declare module "classnames/bind" { 18 | declare module.exports: $Exports<"classnames">; 19 | } 20 | 21 | declare module "classnames/dedupe" { 22 | declare module.exports: $Exports<"classnames">; 23 | } 24 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { configure, addDecorator } from '@storybook/react'; 4 | 5 | // Addons 6 | import { checkA11y } from '@storybook/addon-a11y'; 7 | import { withKnobs } from '@storybook/addon-knobs'; 8 | import centered from '@storybook/addon-centered'; 9 | 10 | // automatically import all files ending in *.stories.js 11 | const req = require.context('../stories', true, /.stories.js$/); 12 | const loadStories = () => req.keys().forEach(req); 13 | 14 | // init the addons 15 | addDecorator(checkA11y); 16 | addDecorator(withKnobs); 17 | addDecorator(centered); 18 | 19 | // Import our CSS 20 | import '../app/css/main.css'; 21 | 22 | configure(loadStories, module); 23 | -------------------------------------------------------------------------------- /app/components/user/graphql/defaults.js: -------------------------------------------------------------------------------- 1 | export const DEFAULT_QUERY_WITH_ORGANIZATION = `# Here is an example query! Check out the "Examples" tab for more. 2 | 3 | query AllPipelinesQuery { 4 | organization(slug: $organizationSlug) { 5 | name 6 | pipelines(first: 3) { 7 | edges { 8 | node { 9 | name 10 | description 11 | repository { 12 | url 13 | } 14 | } 15 | } 16 | } 17 | } 18 | }`; 19 | 20 | export const DEFAULT_QUERY_NO_ORGANIZATION = `# Here is an example query! Check out the "Examples" tab for more. 21 | 22 | query MyDetailsQuery { 23 | viewer { 24 | user { 25 | name 26 | } 27 | } 28 | }`; 29 | -------------------------------------------------------------------------------- /app/components/docs/08-linux.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Linux/Other 3 | slug: linux 4 | emoji: ':linux:' 5 | --- 6 | Run the following script ([view the source](https://raw.githubusercontent.com/buildkite/agent/master/install.sh)), which will download and install the correct binary for your system and architecture: 7 | 8 | ```bash 9 | TOKEN="{{ props.token || 'INSERT-YOUR-AGENT-TOKEN-HERE' }}" bash -c "`curl -sL https://raw.githubusercontent.com/buildkite/agent/master/install.sh`" 10 | ``` 11 | 12 | Then, start the agent: 13 | 14 | ```bash 15 | ~/.buildkite-agent/bin/buildkite-agent start 16 | ``` 17 | 18 |

    See the Linux agent docs for more details.

    19 | -------------------------------------------------------------------------------- /app/images/mark.svg: -------------------------------------------------------------------------------- 1 | icon-square-no-padding -------------------------------------------------------------------------------- /app/components/shared/Icon/svgContent.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Logger from 'app/lib/Logger'; 4 | import escape from 'escape-html'; 5 | 6 | // NOTE: We cast `require` to an Object here so we can call `context`, 7 | // as Flow doesn't understand Webpack's require extensions. 8 | const context = (require: Object).context('!raw-loader!./', false, /\.svg$/); 9 | 10 | export default function svgContent(name: string, title?: string){ 11 | let icon = context('./placeholder.svg'); 12 | 13 | try { 14 | icon = context(`./${name}.svg`); 15 | } catch (err) { 16 | Logger.error(`[Icon] No icon defined for "${name}"`, err); 17 | } 18 | 19 | return (title ? `${escape(title)}` : '') + icon; 20 | } 21 | -------------------------------------------------------------------------------- /app/css/select.css: -------------------------------------------------------------------------------- 1 | .select { 2 | display: block; 3 | width: 100%; 4 | padding: .43em .86em; 5 | font-size: 14px; 6 | line-height: 1.42857143; 7 | height: 2.5em; 8 | color: #555555; 9 | background-color: #fff; 10 | background-image: none; 11 | border: 1px solid #ccc; 12 | border-radius: .3em; 13 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 14 | 15 | &:focus { 16 | border-color: #888; 17 | outline: none; 18 | } 19 | 20 | &.is-error { 21 | border-color: var(--light-red); 22 | } 23 | 24 | &.is-error:focus { 25 | border-color: var(--dark-red); 26 | } 27 | 28 | &:disabled { 29 | color: var(--dark-gray); 30 | background-color: var(--silver); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/components/user/graphql/GraphQLExplorerDocumentation/RootField.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react"; 4 | import { Link } from 'react-router'; 5 | 6 | type Props = { 7 | name: string 8 | }; 9 | 10 | export default class RootField extends React.PureComponent { 11 | render() { 12 | const [type, name] = this.props.name.split("."); 13 | 14 | return ( 15 | 16 | {name} 17 | ( 18 | ) 19 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/lib/repositories.spec.js: -------------------------------------------------------------------------------- 1 | /* global describe, it, expect */ 2 | import { repositoryProviderIcon } from './repositories'; 3 | 4 | const PROVIDERS = [ 5 | 'RepositoryProviderBitbucket', 6 | 'RepositoryProviderCodebase', 7 | 'RepositoryProviderGithub', 8 | 'RepositoryProviderGithubEnterprise', 9 | 'RepositoryProviderGitlab', 10 | 'RepositoryProviderGitlabCommunity', 11 | 'RepositoryProviderUnknown' 12 | ]; 13 | 14 | describe('repositoryProviderIcon', () => { 15 | describe('returns expected icon names', () => { 16 | PROVIDERS.forEach((provider) => { 17 | it(`for ${provider}`, () => { 18 | expect(repositoryProviderIcon(provider)).toMatchSnapshot(); 19 | }); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /app/components/shared/PageWithMenu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default class PageWithMenu extends React.PureComponent { 5 | static propTypes = { 6 | children: PropTypes.node.isRequired 7 | }; 8 | 9 | render() { 10 | const children = React.Children.toArray(this.props.children); 11 | 12 | return ( 13 |
    14 |
    15 |
    16 | {children[0]} 17 |
    18 |
    19 | {children.slice(1)} 20 |
    21 |
    22 |
    23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/lib/__snapshots__/commits.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`shortCommit returns a 7-character SHA1 for a full SHA1 commitish 1`] = `"be9c03b"`; 4 | 5 | exports[`shortCommit returns the full name for a 40-character non-SHA1 commitish 1`] = `"so-this-is-a-forty-character-branch-name"`; 6 | 7 | exports[`shortCommit returns the full name for a non-SHA1 commitish 1`] = `"preload-pipeline-names-sperlunking"`; 8 | 9 | exports[`shortMessage returns the first line of a multi-line message 1`] = `"✨ Somehow this is the first spec I've written for our front-end, and this seems really odd to me"`; 10 | 11 | exports[`shortMessage returns the whole message in a one-line message 1`] = `"Bump frontend"`; 12 | -------------------------------------------------------------------------------- /app/mutations/EmailResendVerification.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay/classic'; 2 | 3 | class EmailResendVerification extends Relay.Mutation { 4 | getMutation() { 5 | return Relay.QL` 6 | mutation { 7 | emailResendVerification 8 | } 9 | `; 10 | } 11 | 12 | getFatQuery() { 13 | return Relay.QL` 14 | fragment on EmailResendVerificationPayload { 15 | email 16 | } 17 | `; 18 | } 19 | 20 | getConfigs() { 21 | return [{ 22 | type: 'FIELDS_CHANGE', 23 | fieldIDs: { 24 | email: this.props.email.id 25 | } 26 | }]; 27 | } 28 | 29 | getVariables() { 30 | return { id: this.props.email.id }; 31 | } 32 | } 33 | 34 | export default EmailResendVerification; 35 | -------------------------------------------------------------------------------- /app/lib/jobs.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import JobStates from 'app/constants/JobStates'; 4 | 5 | export function jobTime(job: Object) { 6 | const { state, startedAt, finishedAt, canceledAt, timedOutAt } = job; 7 | const time = {}; 8 | 9 | // job never stared, so no duration to show 10 | if (!startedAt) { 11 | return time; 12 | } 13 | 14 | time.from = startedAt; 15 | 16 | switch (state) { 17 | case JobStates.FINISHED: 18 | time.to = finishedAt; 19 | break; 20 | 21 | case JobStates.CANCELED: 22 | case JobStates.CANCELING: 23 | time.to = canceledAt; 24 | break; 25 | 26 | case JobStates.TIMED_OUT: 27 | case JobStates.TIMING_OUT: 28 | time.to = timedOutAt; 29 | break; 30 | } 31 | 32 | return time; 33 | } 34 | -------------------------------------------------------------------------------- /app/components/docs/05-docker.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Docker 3 | --- 4 | Start an agent with the [official image](https://hub.docker.com/r/buildkite/agent/) based on Alpine Linux: 5 | 6 | ```bash 7 | docker run -e BUILDKITE_AGENT_TOKEN="{{ props.token || 'INSERT-YOUR-AGENT-TOKEN-HERE' }}" buildkite/agent 8 | ``` 9 | 10 | A much larger Ubuntu-based image is also available: 11 | 12 | ```bash 13 | docker run -e BUILDKITE_AGENT_TOKEN="{{ props.token || 'INSERT-YOUR-AGENT-TOKEN-HERE' }}" buildkite/agent:ubuntu 14 | ``` 15 | 16 |

    Alternatively all our installers are capable of running your builds within isolated Docker containers. Simply install the relevant agent for your system and see our Docker docs for more details.

    17 | -------------------------------------------------------------------------------- /app/css/rouge.css: -------------------------------------------------------------------------------- 1 | .rouge-table pre { 2 | font-family: var(--font-family-mono); 3 | font-size: 12px; 4 | line-height: 17px; 5 | background: inherit; 6 | border: 0; 7 | } 8 | 9 | .rouge-gutter { 10 | min-width: 25px; 11 | padding-right: 8px; 12 | text-align: right; 13 | } 14 | 15 | .rouge-gutter pre { 16 | color: #999; 17 | } 18 | 19 | .rouge-code-json .p { 20 | color: #555; 21 | } 22 | 23 | .rouge-code-json .s2 { 24 | color: #D64292 25 | } 26 | 27 | .rouge-code-graphql .p { 28 | color: #555; 29 | } 30 | 31 | .rouge-code-graphql .s2 { 32 | color: #D64292; 33 | } 34 | 35 | .rouge-code-graphql .k { 36 | color: #B11A04; 37 | } 38 | 39 | .rouge-code-graphql .n { 40 | color: #1F61A0; 41 | } 42 | 43 | .rouge-code-graphql .k + .w + .n { 44 | color: #D2054E; 45 | } 46 | -------------------------------------------------------------------------------- /app/components/shared/FormInputLabel.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | class FormInputLabel extends React.PureComponent { 6 | static propTypes = { 7 | label: PropTypes.node.isRequired, 8 | children: PropTypes.node, 9 | errors: PropTypes.bool, 10 | required: PropTypes.bool 11 | }; 12 | 13 | render() { 14 | return ( 15 | 22 | ); 23 | } 24 | } 25 | 26 | export default FormInputLabel; 27 | -------------------------------------------------------------------------------- /app/lib/words.spec.js: -------------------------------------------------------------------------------- 1 | /* global describe, it, expect */ 2 | import { indefiniteArticleFor } from './words'; 3 | 4 | const TEST_WORDS = [ 5 | 'pipeline', 6 | 'organization', 7 | 'request', 8 | 'dog', 9 | 'cat', 10 | 'ant', 11 | 'clock' 12 | ]; 13 | 14 | describe('indefiniteArticleFor', () => { 15 | describe('correctly identifies indefinite articles', () => { 16 | TEST_WORDS.forEach((word) => { 17 | it(`for “${word}”`, () => { 18 | const articleForWord = indefiniteArticleFor(word); 19 | const articleForUppercaseWord = indefiniteArticleFor(word.toUpperCase()); 20 | 21 | expect(articleForWord).toMatchSnapshot(); 22 | expect(articleForUppercaseWord).toMatchSnapshot(); 23 | expect(articleForWord).toEqual(articleForUppercaseWord); 24 | }); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /app/components/agent/shared.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export function getColourForConnectionState(connectionState: string, prefix: string = '') { 4 | switch (connectionState) { 5 | case 'connected': 6 | return `${prefix}lime`; 7 | case 'disconnected': 8 | case 'stopped': 9 | case 'lost': 10 | case 'never_connected': 11 | return `${prefix}gray`; 12 | case 'stopping': 13 | return `${prefix}orange`; 14 | } 15 | } 16 | 17 | const CONNECTION_STATE_LABELS = { 18 | 'connected': 'Connected', 19 | 'disconnected': 'Disconnected', 20 | 'stopped': 'Stopped', 21 | 'stopping': 'Stopping…', 22 | 'never_connected': 'Never Connected', 23 | 'lost': 'Lost Connection' 24 | }; 25 | 26 | export function getLabelForConnectionState(connectionState: string) { 27 | return CONNECTION_STATE_LABELS[connectionState]; 28 | } 29 | -------------------------------------------------------------------------------- /app/components/layout/Navigation/dropdown-button.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | export default class DropdownButton extends React.PureComponent { 6 | static displayName = "Navigation.DropdownButton"; 7 | 8 | static propTypes = { 9 | style: PropTypes.object, 10 | className: PropTypes.string, 11 | children: PropTypes.node, 12 | onMouseEnter: PropTypes.func 13 | }; 14 | 15 | render() { 16 | return ( 17 | 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/queries/Build.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import Relay from 'react-relay/classic'; 4 | 5 | // Note: Ensure whatever variable you use as the $slug is unique and doesn't 6 | // match any existing variables in any other queries otherwise React Relay 7 | // Router doesn't work very well. 8 | 9 | export const query = () => Relay.QL` 10 | query { 11 | build(slug: $buildSlug) 12 | } 13 | `; 14 | 15 | // Since relay doesn't currently support root fields with multiple 16 | // parameters, it means we can't have queries like: build(org: "...", 17 | // pipeline: "...", number: "12"), so we have to do this hacky thing where we 18 | // include them all in the `buildSlug` param. 19 | export const prepareParams = (params: Object) => { 20 | return { 21 | ...params, 22 | buildSlug: [params.organization, params.pipeline, params.number].join("/") 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /app/components/shared/PermissionDescription.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import Icon from './Icon'; 5 | 6 | export default class PermissionDescription extends React.PureComponent { 7 | static propTypes = { 8 | allowed: PropTypes.bool.isRequired, 9 | permission: PropTypes.string.isRequired 10 | }; 11 | 12 | render() { 13 | const { allowed, permission } = this.props; 14 | 15 | const icon = allowed ? 'permission-small-tick' : 'permission-small-cross'; 16 | const words = allowed ? `Can ${permission}.` : `Can not ${permission}.`; 17 | 18 | return ( 19 |
    20 | 21 | {words} 22 |
    23 | ); 24 | } 25 | } -------------------------------------------------------------------------------- /app/components/shared/UserAvatar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | export default class UserAvatar extends React.PureComponent { 6 | static propTypes = { 7 | user: PropTypes.shape({ 8 | name: PropTypes.string.isRequired, 9 | avatar: PropTypes.shape({ 10 | url: PropTypes.string.isRequired 11 | }) 12 | }).isRequired, 13 | className: PropTypes.string, 14 | style: PropTypes.object 15 | }; 16 | 17 | render() { 18 | return ( 19 | {this.props.user.name} 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/components/shared/PageHeader/icon.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | import styled from 'styled-components'; 5 | 6 | const DivWithSlightRightMargin = styled('div').attrs({ 7 | className: 'align-middle' 8 | })` 9 | /* Slightly less than the mr3 (15px) */ 10 | margin-right: 13px; 11 | `; 12 | 13 | export default class Icon extends React.PureComponent { 14 | static displayName = 'PageHeader.Icon'; 15 | static propTypes = { 16 | children: PropTypes.node.isRequired, 17 | className: PropTypes.string 18 | }; 19 | 20 | render() { 21 | const { className, children } = this.props; 22 | 23 | return ( 24 | 25 | {children} 26 | 27 | ); 28 | } 29 | } -------------------------------------------------------------------------------- /app/components/user/graphql/codemirror.js: -------------------------------------------------------------------------------- 1 | export { default } from 'codemirror'; 2 | 3 | import 'app/css/codemirror.css'; 4 | 5 | import 'codemirror/addon/hint/show-hint.css'; 6 | import 'codemirror/addon/hint/show-hint'; 7 | import 'codemirror/addon/comment/comment'; 8 | import 'codemirror/addon/edit/matchbrackets'; 9 | import 'codemirror/addon/edit/closebrackets'; 10 | import 'codemirror/addon/search/search'; 11 | import 'codemirror/addon/search/searchcursor'; 12 | import 'codemirror/addon/search/jump-to-line'; 13 | import 'codemirror/addon/dialog/dialog.css'; 14 | import 'codemirror/addon/dialog/dialog'; 15 | import 'codemirror/addon/lint/lint'; 16 | import 'codemirror/addon/lint/lint.css'; 17 | import 'codemirror/keymap/sublime'; 18 | import 'codemirror-graphql/results/mode'; 19 | import 'codemirror-graphql/hint'; 20 | import 'codemirror-graphql/lint'; 21 | import 'codemirror-graphql/mode'; 22 | -------------------------------------------------------------------------------- /app/css/btn.css: -------------------------------------------------------------------------------- 1 | .btn, .unstyled-button { 2 | font-family: inherit; 3 | font-size: inherit; 4 | font-weight: 500; 5 | text-decoration: none; 6 | cursor: pointer; 7 | display: inline-block; 8 | line-height: 1.2; 9 | padding: .75em 1em; 10 | margin: 0; 11 | height: auto; 12 | border: 1px solid transparent; 13 | vertical-align: middle; 14 | -webkit-appearance: none; 15 | color: inherit; 16 | background-color: transparent; 17 | } 18 | 19 | .btn.-icon-only { 20 | display: flex; 21 | align-items: center; 22 | padding: 1em; 23 | } 24 | 25 | .btn:hover, .btn:active, .btn:focus { 26 | text-decoration: none; 27 | outline: none; 28 | } 29 | 30 | .btn .emoji { 31 | margin-top: -4px; 32 | margin-bottom: -2px; 33 | } 34 | 35 | ::-moz-focus-inner { 36 | border: 0; 37 | padding: 0; 38 | } 39 | 40 | .unstyled-button { 41 | padding: 0; 42 | line-height: inherit; 43 | border: none; 44 | } -------------------------------------------------------------------------------- /app/lib/__snapshots__/repositories.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`repositoryProviderIcon returns expected icon names for RepositoryProviderBitbucket 1`] = `"bitbucket"`; 4 | 5 | exports[`repositoryProviderIcon returns expected icon names for RepositoryProviderCodebase 1`] = `"git"`; 6 | 7 | exports[`repositoryProviderIcon returns expected icon names for RepositoryProviderGithub 1`] = `"github"`; 8 | 9 | exports[`repositoryProviderIcon returns expected icon names for RepositoryProviderGithubEnterprise 1`] = `"github"`; 10 | 11 | exports[`repositoryProviderIcon returns expected icon names for RepositoryProviderGitlab 1`] = `"gitlab"`; 12 | 13 | exports[`repositoryProviderIcon returns expected icon names for RepositoryProviderGitlabCommunity 1`] = `"gitlab"`; 14 | 15 | exports[`repositoryProviderIcon returns expected icon names for RepositoryProviderUnknown 1`] = `"git"`; 16 | -------------------------------------------------------------------------------- /app/css/btn-primary.css: -------------------------------------------------------------------------------- 1 | .btn-primary { 2 | color: var(--white); 3 | background-color: var(--lime); 4 | border-radius: 3px; 5 | font-weight: inherit; 6 | } 7 | 8 | /* Since we've got bootstrap.css on the page, we need to re-define this class 9 | with more specificity to target a tags. Bootstrap overrides the base colors for 10 | all a-tags, and .btn-primary can't get it's own styles on there. */ 11 | a.btn-primary { 12 | color: var(--white); 13 | } 14 | 15 | .btn-primary:hover { 16 | box-shadow: inset 0 0 0 20rem var(--darken-1); 17 | } 18 | 19 | .btn-primary:focus { 20 | border-color: var(--darken-2); 21 | } 22 | 23 | .btn-primary:active { 24 | outline: 0; 25 | box-shadow: inset 0 0 0 10rem var(--darken-2), 26 | inset 0 3px 4px 0 var(--darken-1), 27 | 0 0 1px var(--darken-1); 28 | } 29 | 30 | .btn-primary:disabled, 31 | .btn-primary.is-disabled { 32 | opacity: .5; 33 | cursor: not-allowed; 34 | } 35 | -------------------------------------------------------------------------------- /app/css/container.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 100%; 3 | margin-left: auto; 4 | margin-right: auto; 5 | padding-left: 15px; 6 | padding-right: 15px; 7 | 8 | @media (min-width: 768px) { 9 | width: 750px; 10 | } 11 | 12 | @media (min-width: 992px) { 13 | width: 970px; 14 | } 15 | 16 | @media (min-width: 1200px) { 17 | width: 1170px; 18 | } 19 | } 20 | 21 | .container-widescreen { 22 | @media (min-width: 1200px) { 23 | width: 100%; 24 | padding-left: 20px; 25 | padding-right: 20px; 26 | } 27 | } 28 | 29 | /* Override the breakpoints set in basscss-hide so they match up with the container 30 | * widths above */ 31 | @custom-media --breakpoint-xs (max-width: 767px); 32 | @custom-media --breakpoint-sm-md (min-width: 768px) and (max-width: 991px); 33 | @custom-media --breakpoint-md-lg (min-width: 992px) and (max-width: 1199px); 34 | @custom-media --breakpoint-lg (min-width: 1200px); 35 | -------------------------------------------------------------------------------- /app/components/organization/SettingsSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Relay from 'react-relay/classic'; 4 | 5 | import PageWithMenu from 'app/components/shared/PageWithMenu'; 6 | import SettingsMenu from './SettingsMenu'; 7 | 8 | class SettingsSection extends React.PureComponent { 9 | static propTypes = { 10 | organization: PropTypes.object.isRequired, 11 | children: PropTypes.node.isRequired 12 | }; 13 | 14 | render() { 15 | return ( 16 | 17 | 18 | {this.props.children} 19 | 20 | ); 21 | } 22 | } 23 | 24 | export default Relay.createContainer(SettingsSection, { 25 | fragments: { 26 | organization: () => Relay.QL` 27 | fragment on Organization { 28 | ${SettingsMenu.getFragment('organization')} 29 | } 30 | ` 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /app/mutations/TeamMemberUpdate.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay/classic'; 2 | 3 | class TeamMemberUpdate extends Relay.Mutation { 4 | static fragments = { 5 | teamMember: () => Relay.QL` 6 | fragment on TeamMember { 7 | id 8 | } 9 | ` 10 | } 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation { 15 | teamMemberUpdate 16 | } 17 | `; 18 | } 19 | 20 | getFatQuery() { 21 | return Relay.QL` 22 | fragment on TeamMemberUpdatePayload { 23 | teamMember { 24 | role 25 | } 26 | } 27 | `; 28 | } 29 | 30 | getConfigs() { 31 | return [{ 32 | type: 'FIELDS_CHANGE', 33 | fieldIDs: { 34 | teamMember: this.props.teamMember.id 35 | } 36 | }]; 37 | } 38 | 39 | getVariables() { 40 | return { id: this.props.teamMember.id, role: this.props.role }; 41 | } 42 | } 43 | 44 | export default TeamMemberUpdate; 45 | -------------------------------------------------------------------------------- /app/components/shared/FormInputErrors.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | 5 | const FormInputErrors = ({ className, errors, ...props }) => { 6 | if (errors.length < 1) { 7 | return null; 8 | } 9 | 10 | return ( 11 |

    12 | {errors.reduce( 13 | (acc, item, index) => { 14 | const separator = ( 15 | index > 0 16 | ? [', '] 17 | : [] 18 | ); 19 | 20 | return acc.concat(separator).concat([item]); 21 | }, 22 | [] 23 | )} 24 |

    25 | ); 26 | }; 27 | 28 | FormInputErrors.propTypes = { 29 | className: PropTypes.string, 30 | errors: PropTypes.arrayOf(PropTypes.node.isRequired) 31 | }; 32 | 33 | FormInputErrors.defaultProps = { 34 | errors: [] 35 | }; 36 | 37 | export default FormInputErrors; 38 | -------------------------------------------------------------------------------- /flow-typed/npm/query-string_v5.1.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 104549010077e5ab3f721b14eec18869 2 | // flow-typed version: d566ab41b9/query-string_v5.1.x/flow_>=v0.32.x 3 | 4 | declare module 'query-string' { 5 | declare type ArrayFormat = 'none' | 'bracket' | 'index' 6 | declare type ParserOptions = {| 7 | arrayFormat?: ArrayFormat, 8 | |} 9 | 10 | declare type StringifyOptions = {| 11 | arrayFormat?: ArrayFormat, 12 | encode?: boolean, 13 | strict?: boolean, 14 | sort?: false | (A, B) => number, 15 | |} 16 | 17 | declare module.exports: { 18 | extract(input: string): string, 19 | parse(input: string, options?: ParserOptions): { [name: string]: string | Array }, 20 | parseUrl(input: string, options?: ParserOptions): { 21 | url: string, 22 | query: { [name: string]: string | Array } 23 | }, 24 | stringify(obj: { [name: string]: mixed }, options?: StringifyOptions): string, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/mutations/TeamPipelineUpdate.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay/classic'; 2 | 3 | class TeamPipelineUpdate extends Relay.Mutation { 4 | static fragments = { 5 | teamPipeline: () => Relay.QL` 6 | fragment on TeamPipeline { 7 | id 8 | } 9 | ` 10 | } 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation { 15 | teamPipelineUpdate 16 | } 17 | `; 18 | } 19 | 20 | getFatQuery() { 21 | return Relay.QL` 22 | fragment on TeamPipelineUpdatePayload { 23 | teamPipeline { 24 | accessLevel 25 | } 26 | } 27 | `; 28 | } 29 | 30 | getConfigs() { 31 | return [{ 32 | type: 'FIELDS_CHANGE', 33 | fieldIDs: { 34 | teamPipeline: this.props.teamPipeline.id 35 | } 36 | }]; 37 | } 38 | 39 | getVariables() { 40 | return { id: this.props.teamPipeline.id, accessLevel: this.props.accessLevel }; 41 | } 42 | } 43 | 44 | export default TeamPipelineUpdate; 45 | -------------------------------------------------------------------------------- /stories/components/icons/BuildState.stories.js: -------------------------------------------------------------------------------- 1 | /* global module */ 2 | 3 | import React from 'react'; 4 | import { storiesOf } from '@storybook/react'; 5 | 6 | import BuildState from '../../../app/components/icons/BuildState'; 7 | import BuildStates from '../../../app/constants/BuildStates'; 8 | 9 | const all = () => ( 10 | 11 | 12 | {Object.keys(BuildStates).map((state) => ( 13 | 14 | 15 | 16 | 17 | ))} 18 | 19 |
    {state}
    20 | ); 21 | 22 | storiesOf('Icons/BuildState', module) 23 | .add('All', all); 24 | 25 | Object.keys(BuildStates).map((state) => { 26 | storiesOf('Icons/BuildState', module) 27 | .add(state, () => ( 28 | 29 | )); 30 | }); 31 | 32 | export const Sketch = all; -------------------------------------------------------------------------------- /app/css/input.css: -------------------------------------------------------------------------------- 1 | .input { 2 | display: block; 3 | width: 100%; 4 | padding: .43em .86em; 5 | font-size: 14px; 6 | line-height: 1.42857143; 7 | color: #555555; 8 | background-color: #fff; 9 | background-image: none; 10 | border: 1px solid #ccc; 11 | border-radius: .3em; 12 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 13 | 14 | /* disable iOS' extra inner shadows */ 15 | appearance: none; 16 | 17 | &::placeholder { 18 | color: var(--dark-gray); 19 | } 20 | 21 | &:focus { 22 | border-color: #888; 23 | outline: 0; 24 | } 25 | 26 | &.borderless { 27 | border-color: #fff; 28 | box-shadow: none; 29 | } 30 | 31 | &.borderless:focus { 32 | border-color: #fff; 33 | } 34 | 35 | &.is-error { 36 | border-color: var(--light-red); 37 | } 38 | 39 | &.is-error:focus { 40 | border-color: var(--dark-red); 41 | } 42 | 43 | &:disabled { 44 | color: var(--dark-gray); 45 | background-color: var(--silver); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/components/shared/Emojify.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import parseEmoji from 'app/lib/parseEmoji'; 5 | 6 | export default class Emojify extends React.PureComponent { 7 | static propTypes = { 8 | text: PropTypes.string, 9 | title: PropTypes.string, 10 | className: PropTypes.string, 11 | style: PropTypes.object 12 | }; 13 | 14 | render() { 15 | const spanProps = {}; 16 | const html = parseEmoji(this.props.text); 17 | 18 | if (html !== this.props.text) { 19 | spanProps.dangerouslySetInnerHTML = { __html: html }; 20 | spanProps.title = this.props.text; 21 | } else { 22 | spanProps.children = this.props.text; 23 | } 24 | 25 | if (this.props.title) { 26 | spanProps.title = this.props.title; 27 | } 28 | 29 | return ( 30 | 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /flow-typed/npm/whatwg-fetch_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: f944369feda367f32efd9154af4148a8 2 | // flow-typed version: <>/whatwg-fetch_v2.0.4/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'whatwg-fetch' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'whatwg-fetch' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'whatwg-fetch/fetch' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'whatwg-fetch/fetch.js' { 31 | declare module.exports: $Exports<'whatwg-fetch/fetch'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/word-wrap_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 624f7135f2a1119374586239aac5b389 2 | // flow-typed version: <>/word-wrap_v1.2.3/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'word-wrap' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'word-wrap' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'word-wrap/index' { 29 | declare module.exports: $Exports<'word-wrap'>; 30 | } 31 | declare module 'word-wrap/index.js' { 32 | declare module.exports: $Exports<'word-wrap'>; 33 | } 34 | -------------------------------------------------------------------------------- /app/css/colors.css: -------------------------------------------------------------------------------- 1 | .black { color: var(--black) } 2 | .gray { color: var(--gray) } 3 | .dark-gray { color: var(--dark-gray) } 4 | .very-dark-gray { color: var(--very-dark-gray) } 5 | .silver { color: var(--silver) } 6 | .white { color: var(--white) } 7 | 8 | .aqua { color: var(--aqua) } 9 | .blue { color: var(--blue) } 10 | .navy { color: var(--navy) } 11 | .teal { color: var(--teal) } 12 | .green { color: var(--green) } 13 | .olive { color: var(--olive) } 14 | .lime { color: var(--lime) } 15 | .dark-lime { color: var(--dark-lime) } 16 | 17 | .yellow { color: var(--yellow) } 18 | .orange { color: var(--orange) } 19 | .light-red { color: var(--light-red) } 20 | .red { color: var(--red) } 21 | .dark-red { color: var(--dark-red) } 22 | .fuchsia { color: var(--fuchsia) } 23 | .purple { color: var(--purple) } 24 | .maroon { color: var(--maroon) } 25 | 26 | .color-inherit { color: inherit } 27 | .muted { opacity: .5 } 28 | -------------------------------------------------------------------------------- /flow-typed/npm/raw-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: e26f92df7773f9763affe1fad638af00 2 | // flow-typed version: <>/raw-loader_v0.5.1/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'raw-loader' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'raw-loader' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'raw-loader/index' { 29 | declare module.exports: $Exports<'raw-loader'>; 30 | } 31 | declare module 'raw-loader/index.js' { 32 | declare module.exports: $Exports<'raw-loader'>; 33 | } 34 | -------------------------------------------------------------------------------- /app/components/shared/Icon/billing.svg: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /app/components/shared/JobLink.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import Relay from 'react-relay/classic'; 5 | import classNames from 'classnames'; 6 | 7 | import JobTitle from './JobTitle'; 8 | 9 | type Props = { 10 | job: { 11 | url: string 12 | }, 13 | className: string, 14 | style: Object 15 | }; 16 | 17 | class JobLink extends React.PureComponent { 18 | render() { 19 | const { job, className, style } = this.props; 20 | 21 | return ( 22 | 30 | 31 | 32 | ); 33 | } 34 | } 35 | 36 | export default Relay.createContainer(JobLink, { 37 | fragments: { 38 | job: () => Relay.QL` 39 | fragment on JobTypeCommand { 40 | ${JobTitle.getFragment('job')} 41 | url 42 | } 43 | ` 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /app/components/user/TwoFactor/TwoFactorConfigure/TotpDeleteMutation.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { graphql, commitMutation } from 'react-relay/compat'; 4 | import type { Environment as RelayEnvironment } from 'react-relay'; 5 | import type { TotpDeleteMutationMutationVariables, TotpDeleteMutationMutationResponse } from './__generated__/TotpCreateMutation.graphql'; 6 | 7 | type MutationParams = { 8 | environment: RelayEnvironment, 9 | onCompleted?: (response: TotpDeleteMutationMutationResponse) => *, 10 | onError?: () => void, 11 | variables?: TotpDeleteMutationMutationVariables 12 | }; 13 | 14 | export default function TotpDeleteMutation({ environment, variables }: MutationParams): void { 15 | commitMutation( 16 | environment, 17 | { 18 | mutation: graphql` 19 | mutation TotpDeleteMutationMutation($input: TOTPDeleteInput!) { 20 | totpDelete(input: $input) { 21 | clientMutationId 22 | } 23 | } 24 | `, 25 | variables 26 | } 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /app/components/user/graphql/GraphQLExplorerDocumentationMutation.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react"; 4 | 5 | import RootField from "./GraphQLExplorerDocumentation/RootField"; 6 | import { getGraphQLSchema } from "./schema"; 7 | 8 | type Props = { 9 | params: { 10 | field: string 11 | } 12 | }; 13 | 14 | export default class GraphQLExplorerDocumentationMutation extends React.PureComponent { 15 | render() { 16 | const fieldname = this.props.params.field; 17 | const schema = getGraphQLSchema(); 18 | const field = schema.getMutationType().getFields()[fieldname]; 19 | 20 | // console.log(field); 21 | 22 | return ( 23 |
    24 |

    Mutation:

    25 | {field.isDeprecated &&

    This mutation is deprecated. {field.deprecationReason}

    } 26 |

    {field.description || 'No description available.'}

    27 |
    {JSON.stringify(field, null, '  ')}
    28 |
    29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /flow-typed/npm/escape-html_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 61d0accc5f710452e30a119650bb38c9 2 | // flow-typed version: <>/escape-html_v^1.0.3/flow_v0.54.1 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'escape-html' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'escape-html' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'escape-html/index' { 29 | declare module.exports: $Exports<'escape-html'>; 30 | } 31 | declare module 'escape-html/index.js' { 32 | declare module.exports: $Exports<'escape-html'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/qrcode.react_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 66561f356f87ed0e75d981a5e995527f 2 | // flow-typed version: <>/qrcode.react_v0.8.0/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'qrcode.react' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'qrcode.react' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'qrcode.react/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'qrcode.react/lib/index.js' { 31 | declare module.exports: $Exports<'qrcode.react/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /app/components/shared/Icon/RevealableDownChevron.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import PropTypes from 'prop-types'; 4 | import styled from 'styled-components'; 5 | 6 | import Icon from 'app/components/shared/Icon'; 7 | 8 | const RevealableDownChevron = styled(Icon).attrs({ 9 | icon: "chevron-right" 10 | })` 11 | transform: rotate(${(props) => props.revealed ? -90 : 90}deg); 12 | trasform-origin: center 0; 13 | transition: transform 300ms; 14 | will-change: transform; 15 | width: ${(props) => props.size}px; 16 | height: ${(props) => props.size}px; 17 | 18 | polyline { 19 | stroke-width: ${(props) => props.strokeWidth}px; 20 | } 21 | `; 22 | 23 | RevealableDownChevron.propTypes = { 24 | revealed: PropTypes.bool, 25 | size: PropTypes.number, 26 | strokeWidth: PropTypes.number, 27 | className: PropTypes.string, 28 | style: PropTypes.object 29 | }; 30 | 31 | RevealableDownChevron.defaultProps = { 32 | revealed: false, 33 | size: 14, 34 | strokeWidth: 2 35 | }; 36 | 37 | export default RevealableDownChevron; 38 | -------------------------------------------------------------------------------- /app/components/shared/Icon/teams.svg: -------------------------------------------------------------------------------- 1 | 4 | 8 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/mutations/OrganizationInvitationResend.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay/classic'; 2 | 3 | export default class OrganizationInvitationResend extends Relay.Mutation { 4 | static fragments = { 5 | organizationInvitation: () => Relay.QL` 6 | fragment on OrganizationInvitation { 7 | id 8 | } 9 | ` 10 | } 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation { 15 | organizationInvitationResend 16 | } 17 | `; 18 | } 19 | 20 | getFatQuery() { 21 | return Relay.QL` 22 | fragment on OrganizationInvitationResendPayload { 23 | organizationInvitation { 24 | id 25 | email 26 | } 27 | } 28 | `; 29 | } 30 | 31 | getConfigs() { 32 | return [{ 33 | type: 'FIELDS_CHANGE', 34 | fieldIDs: { 35 | organizationInvitation: this.props.organizationInvitation.id 36 | } 37 | }]; 38 | } 39 | 40 | getVariables() { 41 | return { id: this.props.organizationInvitation.id }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /flow-typed/npm/buffer-crc32_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: d21d290d9cf4526dde28ef79be5fe83e 2 | // flow-typed version: <>/buffer-crc32_v0.2.13/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'buffer-crc32' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'buffer-crc32' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'buffer-crc32/index' { 29 | declare module.exports: $Exports<'buffer-crc32'>; 30 | } 31 | declare module 'buffer-crc32/index.js' { 32 | declare module.exports: $Exports<'buffer-crc32'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/http-server_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9eb8aad2eaeb3b220c0818da72e15f53 2 | // flow-typed version: <>/http-server_v0.11.1/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'http-server' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'http-server' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'http-server/lib/http-server' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'http-server/lib/http-server.js' { 31 | declare module.exports: $Exports<'http-server/lib/http-server'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/query-string_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 3b6258707a7c0c0214244f1b2202d608 2 | // flow-typed version: <>/query-string_v^4.2.3/flow_v0.54.1 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'query-string' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'query-string' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'query-string/index' { 29 | declare module.exports: $Exports<'query-string'>; 30 | } 31 | declare module 'query-string/index.js' { 32 | declare module.exports: $Exports<'query-string'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/fetch-jsonp_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9069b2bc681aa682fde0586ad200e887 2 | // flow-typed version: <>/fetch-jsonp_v^1.1.1/flow_v0.54.1 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'fetch-jsonp' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'fetch-jsonp' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'fetch-jsonp/build/fetch-jsonp' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'fetch-jsonp/build/fetch-jsonp.js' { 31 | declare module.exports: $Exports<'fetch-jsonp/build/fetch-jsonp'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/ignore-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 0c73136e0aec0f39e4052dcfd21f4815 2 | // flow-typed version: <>/ignore-loader_v0.1.2/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'ignore-loader' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'ignore-loader' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'ignore-loader/index' { 29 | declare module.exports: $Exports<'ignore-loader'>; 30 | } 31 | declare module 'ignore-loader/index.js' { 32 | declare module.exports: $Exports<'ignore-loader'>; 33 | } 34 | -------------------------------------------------------------------------------- /app/components/shared/Panel/row.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | 6 | type Props = { 7 | children: React$Node 8 | }; 9 | 10 | class Row extends React.Component { 11 | static displayName = "Panel.Row"; 12 | 13 | static propTypes = { 14 | children: PropTypes.node.isRequired 15 | }; 16 | 17 | render() { 18 | const children = React.Children.toArray(this.props.children); 19 | 20 | // Filter out the actions from the rest of the children 21 | const nodes = []; 22 | let actions; 23 | children.forEach((child) => { 24 | if (child.type && child.type.displayName === "Panel.RowActions") { 25 | actions = child; 26 | } else { 27 | nodes.push(child); 28 | } 29 | }); 30 | 31 | return ( 32 |
    33 |
    34 | {nodes} 35 |
    36 | {actions} 37 |
    38 | ); 39 | } 40 | } 41 | 42 | export default Row; 43 | -------------------------------------------------------------------------------- /flow-typed/npm/exports-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 134c7e273af8e114f82ebb5428394398 2 | // flow-typed version: <>/exports-loader_v0.7.0/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'exports-loader' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'exports-loader' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'exports-loader/index' { 29 | declare module.exports: $Exports<'exports-loader'>; 30 | } 31 | declare module 'exports-loader/index.js' { 32 | declare module.exports: $Exports<'exports-loader'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/imports-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: bba9a073875551baae4c947ca66de207 2 | // flow-typed version: <>/imports-loader_v0.8.0/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'imports-loader' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'imports-loader' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'imports-loader/index' { 29 | declare module.exports: $Exports<'imports-loader'>; 30 | } 31 | declare module 'imports-loader/index.js' { 32 | declare module.exports: $Exports<'imports-loader'>; 33 | } 34 | -------------------------------------------------------------------------------- /app/css/style-guide/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import Typography from './typography'; 5 | 6 | const Section = function(props) { 7 | return
    {props.children}
    ; 8 | }; 9 | Section.propTypes = { 10 | children: PropTypes.node 11 | }; 12 | 13 | // Useful when authoring our base CSS styles 14 | // 15 | // We don't yet have a static page/route to render this, so at the moment 16 | // you just have to insert it into pages as you need it. 17 | // 18 | // For example: 19 | // 20 | // import CSSStyleGuide from '../../css/style-guide'; 21 | // 22 | // class SomeComponent extends React.Component { 23 | // render() { 24 | // return ( 25 | //
    26 | // 27 | //
    28 | // ); 29 | // } 30 | // } 31 | export default class CSSStyleGuide extends React.PureComponent { 32 | render() { 33 | return ( 34 |
    35 |
    36 |
    37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /flow-typed/npm/postcss-easings_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: fd45654e04d69129c9bb814116a00537 2 | // flow-typed version: <>/postcss-easings_v1.0.1/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'postcss-easings' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'postcss-easings' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'postcss-easings/index' { 29 | declare module.exports: $Exports<'postcss-easings'>; 30 | } 31 | declare module 'postcss-easings/index.js' { 32 | declare module.exports: $Exports<'postcss-easings'>; 33 | } 34 | -------------------------------------------------------------------------------- /app/components/shared/Icon/emails.svg: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-flow_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9f352918b29581eaa8a424848ec677ed 2 | // flow-typed version: <>/babel-preset-flow_v6.23.0/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-flow' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-flow' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-flow/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-flow/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-flow/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /stories/shared/Icon.stories.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /* global module */ 3 | 4 | import React from 'react'; 5 | import { storiesOf } from '@storybook/react'; 6 | import Icon from '../../app/components/shared/Icon'; 7 | 8 | // $FlowExpectError 9 | const iconFiles = require.context('../../app/components/shared/Icon', true, /\.svg$/); 10 | 11 | // keys look like './api-tokens.svg' but we need the 'api-token' part 12 | const icons = iconFiles.keys().map((filename) => filename.replace(/^\.\//, '').replace(/\.svg$/, '')); 13 | 14 | const iconSheet = () => ( 15 |
    16 | {icons.map((icon) => ( 17 | 18 | 19 | 20 | 21 | 22 | ))} 23 |
    24 | ); 25 | 26 | storiesOf('Icon', module).add('All', iconSheet); 27 | 28 | export const Sketch = iconSheet; 29 | 30 | icons.forEach((icon) => { 31 | storiesOf('Icon', module).add(icon, () => 32 | 33 | ); 34 | }); -------------------------------------------------------------------------------- /app/components/user/graphql/GraphQLExplorerDocumentationQuery.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react"; 4 | 5 | import RootField from "./GraphQLExplorerDocumentation/RootField"; 6 | import { getGraphQLSchema } from "./schema"; 7 | 8 | type Props = { 9 | params: { 10 | field: string 11 | } 12 | }; 13 | 14 | export default class GraphQLExplorerDocumentationQuery extends React.PureComponent { 15 | render() { 16 | const fieldname = this.props.params.field; 17 | const schema = getGraphQLSchema(); 18 | const field = schema.getQueryType().getFields()[fieldname]; 19 | 20 | // console.log(field); 21 | 22 | return ( 23 |
    24 |

    Query:

    25 | {field.isDeprecated &&

    This query is deprecated. {field.deprecationReason}

    } 26 |

    {field.description || 'No description available.'}

    27 |

    Arguments

    28 |

    Returns

    29 |
    {JSON.stringify(field, null, '  ')}
    30 |
    31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/stores/PusherStore.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import EventEmitter from 'eventemitter3'; 4 | import Pusher from 'pusher-js'; 5 | import Logger from 'app/lib/Logger'; 6 | 7 | class PusherStore extends EventEmitter { 8 | pusher: Pusher; 9 | 10 | constructor() { 11 | super(); 12 | } 13 | 14 | configure(key: string, options: Object) { 15 | this.pusher = new Pusher(key, options); 16 | this.pusher.connection.bind( 17 | 'state_change', 18 | ({ current, ...context }) => { 19 | Logger.info('[PusherStore]', current, context); 20 | 21 | this.emit(current, context); 22 | } 23 | ); 24 | } 25 | 26 | isConfigured() { 27 | return !!this.pusher; 28 | } 29 | 30 | listen(channel: string) { 31 | Logger.info(`[PusherStore] Listening to channel '${channel}'`); 32 | 33 | this.pusher.subscribe(channel).bind_global((event, payload) => { 34 | Logger.info('[PusherStore]', event, payload); 35 | 36 | this.emit(event, payload); 37 | }); 38 | } 39 | } 40 | 41 | export default new PusherStore(); 42 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-react_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 35549820087f04141f3ab3c8b3cb4691 2 | // flow-typed version: <>/babel-preset-react_v6.24.1/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-react' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-react' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-react/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-react/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-react/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/global_v4.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 79835d69595840752286b1c47d71deba 2 | // flow-typed version: 88a77ba9f4/global_v4.x.x/flow_>=v0.52.x 3 | 4 | declare module 'global' { 5 | declare module.exports: typeof window; 6 | } 7 | 8 | declare module 'global/console' { 9 | declare module.exports: typeof console; 10 | } 11 | 12 | declare module 'global/document' { 13 | declare module.exports: Document; 14 | } 15 | 16 | declare module 'global/process' { 17 | declare module.exports: Process; 18 | } 19 | 20 | declare module 'global/window' { 21 | declare module.exports: typeof window; 22 | } 23 | 24 | // Filename aliases 25 | declare module 'global/console.js' { 26 | declare module.exports: $Exports<'global/console'>; 27 | } 28 | declare module 'global/document.js' { 29 | declare module.exports: $Exports<'global/document'>; 30 | } 31 | declare module 'global/process.js' { 32 | declare module.exports: $Exports<'global/process'>; 33 | } 34 | declare module 'global/window.js' { 35 | declare module.exports: $Exports<'global/window'>; 36 | } 37 | -------------------------------------------------------------------------------- /app/components/shared/Icon/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | import update from 'react-addons-update'; 6 | import svgContent from './svgContent'; 7 | 8 | type Props = { 9 | style?: Object, 10 | className?: string, 11 | icon: string, 12 | title?: string 13 | }; 14 | 15 | function Icon(props: Props) { 16 | const style = update(props.style || {}, { 17 | fill: { 18 | $set: "currentColor" 19 | }, 20 | verticalAlign: { 21 | $set: "middle" 22 | } 23 | }); 24 | 25 | return ( 26 | 36 | ); 37 | } 38 | 39 | Icon.propTypes = { 40 | icon: PropTypes.string.isRequired, 41 | title: PropTypes.string, 42 | className: PropTypes.string, 43 | style: PropTypes.object 44 | }; 45 | 46 | export default Icon; 47 | -------------------------------------------------------------------------------- /app/components/shared/__snapshots__/labelledFormComponent.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`labelledFormComponent exposes a \`focus\` function 1`] = ` 4 | Object { 5 | "configurable": true, 6 | "enumerable": false, 7 | "value": [Function], 8 | "writable": true, 9 | } 10 | `; 11 | 12 | exports[`labelledFormComponent exposes a \`value\` getter 1`] = ` 13 | Object { 14 | "configurable": true, 15 | "enumerable": false, 16 | "get": [Function], 17 | "set": [Function], 18 | } 19 | `; 20 | 21 | exports[`labelledFormComponent exposes specified proxy methods 1`] = ` 22 | Object { 23 | "configurable": true, 24 | "enumerable": true, 25 | "value": [Function], 26 | "writable": true, 27 | } 28 | `; 29 | 30 | exports[`labelledFormComponent renders DOM element children as expected 1`] = ` 31 |
    34 | 44 |
    45 | `; 46 | -------------------------------------------------------------------------------- /app/components/shared/Panel/intro-with-button.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | 6 | type Props = { 7 | children: React$Node 8 | }; 9 | 10 | export default class IntroWithButton extends React.PureComponent { 11 | static displayName = "Panel.IntroWithButton"; 12 | 13 | static propTypes = { 14 | children: PropTypes.node.isRequired 15 | }; 16 | 17 | render() { 18 | const children = React.Children.toArray(this.props.children); 19 | 20 | let intro; 21 | let button; 22 | if (children.length === 1) { 23 | intro = children; 24 | } else { 25 | button = children.pop(); 26 | intro = children; 27 | } 28 | 29 | if (button) { 30 | button = ( 31 |
    32 | {button} 33 |
    34 | ); 35 | } 36 | 37 | return ( 38 |
    39 |
    {intro}
    40 | {button} 41 |
    42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/components/shared/Icon/notification-services.svg: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /app/mutations/APIAccessTokenCodeAuthorize.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay/classic'; 2 | 3 | class APIAccessTokenCodeAuthorize extends Relay.Mutation { 4 | static fragments = { 5 | apiAccessTokenCode: () => Relay.QL` 6 | fragment on APIAccessTokenCode { 7 | id 8 | } 9 | ` 10 | } 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation { 15 | apiAccessTokenCodeAuthorize 16 | } 17 | `; 18 | } 19 | 20 | getFatQuery() { 21 | return Relay.QL` 22 | fragment on APIAccessTokenCodeAuthorizeMutationPayload { 23 | apiAccessTokenCode { 24 | authorizedAt 25 | authorizedIPAddress 26 | } 27 | } 28 | `; 29 | } 30 | 31 | getConfigs() { 32 | return [{ 33 | type: 'FIELDS_CHANGE', 34 | fieldIDs: { 35 | apiAccessTokenCode: this.props.apiAccessTokenCode.id 36 | } 37 | }]; 38 | } 39 | 40 | getVariables() { 41 | return { id: this.props.apiAccessTokenCode.id }; 42 | } 43 | } 44 | 45 | export default APIAccessTokenCodeAuthorize; 46 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-stage-0_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 18a4b2b0f57d1e23b11ff6609f58105f 2 | // flow-typed version: <>/babel-preset-stage-0_v6.24.1/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-stage-0' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-stage-0' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-stage-0/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-stage-0/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-stage-0/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /app/components/team/Labels.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | import { createFragmentContainer, graphql } from 'react-relay/compat'; 6 | import TeamPrivacyConstants from 'app/constants/TeamPrivacyConstants'; 7 | import Badge from 'app/components/shared/Badge'; 8 | import type { Labels_team } from './__generated__/Labels_team.graphql'; 9 | 10 | type Props = { 11 | team: Labels_team 12 | }; 13 | 14 | class TeamLabels extends React.PureComponent { 15 | static propTypes = { 16 | team: PropTypes.shape({ 17 | privacy: PropTypes.string.isRequired 18 | }) 19 | } 20 | 21 | render() { 22 | if (this.props.team.privacy === TeamPrivacyConstants.SECRET) { 23 | return ( 24 |
    25 | Secret 26 |
    27 | ); 28 | } 29 | return null; 30 | 31 | } 32 | } 33 | 34 | export default createFragmentContainer(TeamLabels, graphql` 35 | fragment Labels_team on Team { 36 | privacy 37 | } 38 | `); -------------------------------------------------------------------------------- /app/mutations/NoticeDismiss.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay/classic'; 2 | 3 | class NoticeDismiss extends Relay.Mutation { 4 | static fragments = { 5 | notice: () => Relay.QL` 6 | fragment on Notice { 7 | id 8 | } 9 | ` 10 | } 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation { 15 | noticeDismiss 16 | } 17 | `; 18 | } 19 | 20 | getFatQuery() { 21 | return Relay.QL` 22 | fragment on NoticeDismissPayload { 23 | notice { 24 | dismissedAt 25 | } 26 | } 27 | `; 28 | } 29 | 30 | getOptimisticResponse() { 31 | return { 32 | notice: { 33 | id: this.props.notice.id, 34 | dismissedAt: (new Date()).toString() 35 | } 36 | }; 37 | } 38 | 39 | getConfigs() { 40 | return [{ 41 | type: 'FIELDS_CHANGE', 42 | fieldIDs: { 43 | notice: this.props.notice.id 44 | } 45 | }]; 46 | } 47 | 48 | getVariables() { 49 | return { id: this.props.notice.id }; 50 | } 51 | } 52 | 53 | export default NoticeDismiss; 54 | -------------------------------------------------------------------------------- /flow-typed/npm/stats-webpack-plugin_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: f70989c86f49fbb0213e47230aeba908 2 | // flow-typed version: <>/stats-webpack-plugin_v0.6.2/flow_v0.69.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'stats-webpack-plugin' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'stats-webpack-plugin' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'stats-webpack-plugin/index' { 29 | declare module.exports: $Exports<'stats-webpack-plugin'>; 30 | } 31 | declare module 'stats-webpack-plugin/index.js' { 32 | declare module.exports: $Exports<'stats-webpack-plugin'>; 33 | } 34 | -------------------------------------------------------------------------------- /app/components/job/Index/search-input.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import Icon from 'app/components/shared/Icon'; 5 | 6 | export default class SearchInput extends React.PureComponent { 7 | static propTypes = { 8 | value: PropTypes.string, 9 | onChange: PropTypes.func 10 | }; 11 | 12 | render() { 13 | return ( 14 |
    15 | 20 | 21 | 31 |
    32 | ); 33 | } 34 | 35 | handleInputChange = (event) => { 36 | this.props.onChange(event); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/components/shared/Panel/row-actions.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | import classNames from 'classnames'; 6 | 7 | type Props = { 8 | children?: React$Node, 9 | className?: string 10 | }; 11 | 12 | export default class RowActions extends React.PureComponent { 13 | static displayName = "Panel.RowActions"; 14 | 15 | static propTypes = { 16 | children: PropTypes.node, 17 | className: PropTypes.string 18 | }; 19 | 20 | render() { 21 | const children = React.Children.toArray(this.props.children); 22 | 23 | // Since this component is a wrapper for other components, we can't return 24 | // null if there aren't any children (otherwise React seems to bork). 25 | // Returning a