Skip to content

Commit

Permalink
Merge Collections project into master (#7752)
Browse files Browse the repository at this point in the history
* Entity pages (courtesy @kdoh)

* Add collection_id to Dashboards & Pulses (#7358)

* add search to top nav

* flip homepage, updated collections

* make recent views self contained, add to home

* recent items style, add some new colors

* adjust default text color

* add js colors to style guide

* add copy color

* segment loader

* move to landings

* landing nav

* segment list + loader

* clean up landing nav

* metric + segment listing

* mucking around with selectable stuff

* layout tweaks

* other loaders

* stronger left sidebar

* left sidebar

* fix landing

* layout port

* more tweaks

* nav tweaks

* explore

* collection wrap

* Add collection_id to Dashboards & Pulses

* GET /api/collection/:id default to returning everything. Wow!

* colleciton items loader

* dashboard move modal + cleanup

* currentCollection and items

* Add GET /api/collection/root endpoint

* pulse move modal

* MASSIVE ALERTS/PULSES/NOTIFICATIONS OVERHAUL

* move activity feed

* all items, cards

* link

* Filter out stuff you're not allowed to see from the so-called "Root" Collection

* Tests for GET /api/collection/root

* fix query builder and login layout

* lint + test fixes

* filter collection landing

* create dash modal

* new collection modal

* Tests for Dashboard + Collection permissions

* Tests for Pulse + Collection permissions

* Add new Pulse/Alert perms tests & lots of cleanup 🚿

* Test fixes 🔧

* tweak grid, add system to icon

* truncate long titles

* remove duplicate file

* add collection to create dashboard

* add collection selection to pulse edit

* icon spacing

* use site name for landing

* clean up routes

* include required pulse card keys

* fix entity menu action / link and add to collection landing

* update jest snapshots changed by icon

* use entity loader for collections

* use object loader for collection items

* fix colleciton edit and permissions

* remove unused file

* add key to collection grid items

* link to pulse edit

* use named list for collections

* Increase nav z-index Fixes #7523

* tweak z-index level

* fix filters

* fitViewport component and application

* add fitViewport to setup and post setup

* add root collection to dashboard move modal

* move to id for loading collections

* fix permission editor

* fix other instances of collection slug

* fix unit tests

* flow fixes

* dep flow fixes

* Fix admin routes not loading currentUser before checking auth

* Add id: root to Root Collection

* root collection items

* temporary archive links

* fix up question archive route

* redirect to collection on pulse creation

* use fitClasses on /explore

* Fix NavBar popover and modal interactions

* Fix comments about when migrations were added

* fix lint

* style updates

* fix recent views

* collection empty state

* Make FitViewPort more robust

* Fix side bar link states

* fix snapshot

* Fix alerts

* update link and landing nav style

* add archive collection route / modal

* add modal

* Disable onboarding integration test

* Fix disabling of dashbaord tests

* Update snapshots and lint error

* Fix collection archiving

* lint

* revert text color

* Reload collection list each time it's shown to ensure it's in the correct state:

* fix empty state image

* only show permissions edit option for the root collection

* nav

* simple layout

* fix grid

* grid component

* fix translation

* fitClassNames > fitClasses

* fix up collection items loader

* remove unused files

* remove type filter

* qb lives

* default to qb

* collection landing and components

* hoverable card

* placeholder search bar

* flip collection / content order on landing

* fix padding

* dashboards first in the list

* Merge master into collections-project

* only show sidebar if exists

* Add collection_position column to Card/Dashboard/Notification (#7675)

* add first version of pins

* Fix memory leak found using RedShift JDBC Metadata methods

Running sync calls several JDBC metadata methods that return
`ResultSet` objects. According to the JDBC spec, when the connection
associated to the JDBC ResultSet has been closed, it should free the
resources used by the ResultSets that were left open in that
connection. That doesn't look to be happening in RedShift. Closing the
ResutSet instance ourselves before the connection closes will ensure
that these resources are freed and doesn't allow the RedShift bug to
occur.

* use entity update instead of raw api

* Fix tests 🔧😒

* Unified archive, search, schema data browsing, and refactor of entities

* Fix create dashboard modal

* Collections overworld (#7687)

* add overworld

* layout tweaks

* remove navbar browsing link

* table item cards

* search page layout and item icon colors

* search bar active style

* Remove Label & CardLabel models & endpoints

* DO NOT RUN TESTS ON SHUTDOWN! EVER!

* remove navbar browsing link

* table item cards

* search page layout and item icon colors

* search bar active style

* archive page changes

* Merge master into collections-project 😳

* activity style updates

* match search bar width to content

* schema grid

* greet with name

* type sync

* pin icon

* be round now

* search spacing and entitiy item last child border

* collection text color

* collection pinned item size / text

* better root collection name

* something styled

* init search empty state

* lint fix

* fix colleciton links. fixes #7716 (#7720)

* Merge master into collections-project 😳

* database card styling

* tweak hex value

* prettier

* fix overlap (#7737)

* Reload collections list in question save modal, and collections items list as stopgap until it's more automatic (#7731)

* Fix public question layout (#7732)

* Change Urls.collection() to take an ID, default to 'root', and use when creating pulse

* Collections project bg sync (#7740)

* default to bg-slate-extra-light color

* admin routes

* fix question archive redirect and archived message (#7730)
  • Loading branch information
kdoh committed May 29, 2018
1 parent fe249c3 commit 1051eba
Show file tree
Hide file tree
Showing 180 changed files with 7,600 additions and 5,979 deletions.
1 change: 1 addition & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"plugins": [
"babel-plugin-styled-components",
"transform-flow-strip-types",
"add-react-displayname",
"transform-decorators-legacy",
Expand Down
4 changes: 4 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
.*/node_modules/react-element-to-jsx-string/.*
.*/node_modules/resize-observer-polyfill/.*
.*/node_modules/react-virtualized/.*
.*/node_modules/styled-components/.*
.*/node_modules/update-notifier/.*
.*/node_modules/boxen/.*
.*/node_modules/libnpx/.*

[include]
.*/frontend/.*
Expand Down
9 changes: 0 additions & 9 deletions docs/administration-guide/06-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,5 @@ You can archive collections similarly to how you can archive questions. Click th

To restore a collection and its contents, click the `View Archive` icon in the top-right of the main Questions screen to see the archive, then hover over an item to reveal the `Unarchive` icon on the far right of the item. Questions within archived collections are not individually listed in the archive, so if you want to unarchive a specific question from an archived collection, you have to unarchive that whole collection.

### What about labels?
Older versions of Metabase provided labels as a way to organize and filter saved questions. If you were already using labels, you'll still be able to edit and use them for now from the Labels dropdown on lists of saved questions. However, **labels will be removed from Metabase in an upcoming version.** If your instance of Metabase was not using labels previously, you won't see the label tools at all anymore.

What should you do if you want to prepare for the impending removal of labels? We recommend creating collections that match your most important labels, and moving the matching labeled questions into those collections.

If you don't want to remove all the labels from your questions yet, we recommend at least ensuring that none of your questions have more than a single label. That way, if in the future we provide a migration tool that converts labels to collections automatically, there won't be any ambiguity with your labels.

---

## Next: custom segments and metrics
Learn how to define custom segments and commonly referenced metrics in the [next section](07-segments-and-metrics.md).
3 changes: 0 additions & 3 deletions docs/users-guide/06-sharing-answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ After your team has been using Metabase for a while, you’ll probably end up wi
#### Collections
Administrators of Metabase can create collections to put saved questions in. Depending on the permissions you've been given to collections, you'll be able to view the questions inside, edit them, and move questions from one collection to another. Questions that aren't saved in any collection will appear in the "Everything else" section of the main Questions page, and are visible to all Metabase users in your organization. If you're an administrator of your Metabase instance, here are [instructions for creating collections and managing permissions](../administration-guide/06-collections.md).

#### Labels
Older versions of Metabase included a way to add labels to your questions, but this feature will be going away in a future version of Metabase. Currently, if your team was already using labels, you'll still be able to edit and apply them to questions. Here are some [suggestions for switching from labels to collections](../administration-guide/06-collections.html#what-about-labels).

#### Shortcuts
At the top of lists of saved questions you’ll find a dropdown with shortcuts to your favorite questions (mark a question as a favorite by clicking on the star icon that appears when you hover over it), questions you’ve recently viewed, questions that you’ve saved personally, and popular questions that are used the most by your team.

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/metabase-lib/lib/Alert.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const getDefaultAlert = (question, user, visualizationSettings) => {
};

return {
card: { id: question.id() },
card: { id: question.id(), include_csv: false, include_xls: false },
channels: [defaultEmailChannel],
...typeDependentAlertFields,
};
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/metabase-lib/lib/queries/StructuredQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,10 +484,11 @@ export default class StructuredQuery extends AtomicQuery {

/**
* @returns @type {Segment}s that can be used as filters.
* TODO: exclude used segments
*/
filterSegmentOptions(): Segment[] {
return this.table().segments.filter(sgmt => sgmt.is_active === true);
return this.table().segments.filter(
sgmt => sgmt.is_active === true && !this.segments().includes(sgmt),
);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/metabase/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export default class App extends Component {
}

return (
<div className="spread flex flex-column">
<Navbar location={location} className="flex-no-shrink" />
<div className="relative">
<Navbar location={location} />
{errorPage ? getErrorComponent(errorPage) : children}
<UndoListing />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React, { Component } from "react";
import { connect } from "react-redux";

import fitViewport from "metabase/hoc/FitViewPort";

import PermissionsApp from "./PermissionsApp.jsx";

import { PermissionsApi } from "metabase/services";
import { fetchRealDatabases } from "metabase/redux/metadata";

@connect(null, { fetchRealDatabases })
@fitViewport
export default class DataPermissionsApp extends Component {
componentWillMount() {
this.props.fetchRealDatabases(true);
Expand All @@ -17,6 +20,7 @@ export default class DataPermissionsApp extends Component {
{...this.props}
load={PermissionsApi.graph}
save={PermissionsApi.updateGraph}
fitClassNames={this.props.fitClassNames}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default class PermissionsApp extends Component {
};
render() {
return (
<div className="flex-full flex">
<div className={this.props.fitClassNames}>
{this.props.children}
<Modal isOpen={this.state.nextLocation}>
<ConfirmContent
Expand Down
84 changes: 84 additions & 0 deletions frontend/src/metabase/admin/routes.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React from "react";
import { Route } from "metabase/hoc/Title";
import { IndexRoute, IndexRedirect } from "react-router";
import { t } from "c-3po";

// Settings
import SettingsEditorApp from "metabase/admin/settings/containers/SettingsEditorApp.jsx";

// DB Add / list
import DatabaseListApp from "metabase/admin/databases/containers/DatabaseListApp.jsx";
import DatabaseEditApp from "metabase/admin/databases/containers/DatabaseEditApp.jsx";

// Metadata / Data model
import MetadataEditorApp from "metabase/admin/datamodel/containers/MetadataEditorApp.jsx";
import MetricApp from "metabase/admin/datamodel/containers/MetricApp.jsx";
import SegmentApp from "metabase/admin/datamodel/containers/SegmentApp.jsx";
import RevisionHistoryApp from "metabase/admin/datamodel/containers/RevisionHistoryApp.jsx";
import AdminPeopleApp from "metabase/admin/people/containers/AdminPeopleApp.jsx";
import FieldApp from "metabase/admin/datamodel/containers/FieldApp.jsx";
import TableSettingsApp from "metabase/admin/datamodel/containers/TableSettingsApp.jsx";

// People
import PeopleListingApp from "metabase/admin/people/containers/PeopleListingApp.jsx";
import GroupsListingApp from "metabase/admin/people/containers/GroupsListingApp.jsx";
import GroupDetailApp from "metabase/admin/people/containers/GroupDetailApp.jsx";

import getAdminPermissionsRoutes from "metabase/admin/permissions/routes.jsx";

const getRoutes = (store, IsAdmin) => (
<Route path="/admin" title={t`Admin`} component={IsAdmin}>
<IndexRedirect to="/admin/settings" />

<Route path="databases" title={t`Databases`}>
<IndexRoute component={DatabaseListApp} />
<Route path="create" component={DatabaseEditApp} />
<Route path=":databaseId" component={DatabaseEditApp} />
</Route>

<Route path="datamodel" title={t`Data Model`}>
<IndexRedirect to="database" />
<Route path="database" component={MetadataEditorApp} />
<Route path="database/:databaseId" component={MetadataEditorApp} />
<Route path="database/:databaseId/:mode" component={MetadataEditorApp} />
<Route
path="database/:databaseId/:mode/:tableId"
component={MetadataEditorApp}
/>
<Route
path="database/:databaseId/:mode/:tableId/settings"
component={TableSettingsApp}
/>
<Route
path="database/:databaseId/:mode/:tableId/:fieldId"
component={FieldApp}
/>
<Route path="metric/create" component={MetricApp} />
<Route path="metric/:id" component={MetricApp} />
<Route path="segment/create" component={SegmentApp} />
<Route path="segment/:id" component={SegmentApp} />
<Route path=":entity/:id/revisions" component={RevisionHistoryApp} />
</Route>

{/* PEOPLE */}
<Route path="people" title={t`People`} component={AdminPeopleApp}>
<IndexRoute component={PeopleListingApp} />
<Route path="groups" title={t`Groups`}>
<IndexRoute component={GroupsListingApp} />
<Route path=":groupId" component={GroupDetailApp} />
</Route>
</Route>

{/* SETTINGS */}
<Route path="settings" title={t`Settings`}>
<IndexRedirect to="/admin/settings/setup" />
{/* <IndexRoute component={SettingsEditorApp} /> */}
<Route path=":section/:authType" component={SettingsEditorApp} />
<Route path=":section" component={SettingsEditorApp} />
</Route>

{getAdminPermissionsRoutes(store)}
</Route>
);

export default getRoutes;
17 changes: 16 additions & 1 deletion frontend/src/metabase/alert/alert.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ export const createAlert = alert => {
};
};

// NOTE: backend is a little picky about the properties present on the alert
function cleanAlert(alert) {
alert = {
...alert,
card: _.pick(alert.card, "id", "include_csv", "include_xls"),
};
if (alert.collection_id == null) {
delete alert.collection_id;
}
if (alert.alert_above_goal == null) {
delete alert.alert_above_goal;
}
return alert;
}

export const UPDATE_ALERT = "metabase/alerts/UPDATE_ALERT";
const updateAlertRequest = new RestfulRequest({
endpoint: AlertApi.update,
Expand All @@ -83,7 +98,7 @@ const updateAlertRequest = new RestfulRequest({
});
export const updateAlert = alert => {
return async (dispatch, getState) => {
await dispatch(updateAlertRequest.trigger(alert));
await dispatch(updateAlertRequest.trigger(cleanAlert(alert)));

dispatch(
addUndo(
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/metabase/auth/containers/LoginApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export default class LoginApp extends Component {
const ldapEnabled = Settings.ldapEnabled();

return (
<div className="full-height full bg-white flex flex-column flex-full md-layout-centered">
<div className="viewport-height full bg-white flex flex-column flex-full md-layout-centered">
<div className="Login-wrapper wrapper Grid Grid--full md-Grid--1of2 relative z2">
<div className="Grid-cell flex layout-centered text-brand">
<LogoIcon className="Logo my4 sm-my0" width={66} height={85} />
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/metabase/components/ActivityFeed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";
import HomepageApp from "metabase/home/containers/HomepageApp";

class ActivityFeed extends React.Component {
render() {
return <HomepageApp />;
}
}

export default ActivityFeed;
49 changes: 49 additions & 0 deletions frontend/src/metabase/components/ArchiveCollectionModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from "react";
import { connect } from "react-redux";
import { Box, Flex, Text } from "rebass";
import { withRouter } from "react-router";
import { push } from "react-router-redux";
import { t } from "c-3po";

import Button from "metabase/components/Button";
import ModalContent from "metabase/components/ModalContent.jsx";

import Collections from "metabase/entities/collections";

const mapDispatchToProps = {
setCollectionArchived: Collections.actions.setArchived,
push,
};

@connect(null, mapDispatchToProps)
@withRouter
class ArchiveCollectionModal extends React.Component {
async _archive() {
await this.props.setCollectionArchived(
{ id: this.props.params.collectionId },
true,
);
this.props.push("/");
}
render() {
return (
<ModalContent
title={t`Archive this collection?`}
onClose={() => this.props.onClose()}
>
<Box px={3}>
<Text>
{t`The dashboards, collections, and pulses in this collection will also be archived.`}
</Text>
<Flex py={3}>
<Button warning ml="auto" onClick={() => this._archive()}>
{t`Archive`}
</Button>
</Flex>
</Box>
</ModalContent>
);
}
}

export default ArchiveCollectionModal;
4 changes: 3 additions & 1 deletion frontend/src/metabase/components/Archived.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import EmptyState from "metabase/components/EmptyState";
import Link from "metabase/components/Link";
import { t } from "c-3po";

import fitViewport from "metabase/hoc/FitViewPort";

// TODO: port to ErrorMessage for more consistent style

const Archived = ({ entityName, linkTo }) => (
Expand All @@ -23,4 +25,4 @@ const Archived = ({ entityName, linkTo }) => (
</div>
);

export default Archived;
export default fitViewport(Archived);
8 changes: 1 addition & 7 deletions frontend/src/metabase/components/ArchivedItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,7 @@ const ArchivedItem = ({
<Icon name={icon} className="mr2" style={{ color: color }} size={20} />
{name}
{isAdmin && (
<Tooltip
tooltip={
type === "card"
? t`Unarchive this question`
: t`Unarchive this ${type}`
}
>
<Tooltip tooltip={t`Unarchive this ${type}`}>
<Icon
onClick={onUnarchive}
className="ml-auto cursor-pointer text-brand-hover hover-child"
Expand Down
Loading

0 comments on commit 1051eba

Please sign in to comment.