[ARVADOS-WORKBENCH2] updated: 1.3.0-212-gf9dde5c7

Git user git at public.curoverse.com
Tue Dec 18 04:40:00 EST 2018


Summary of changes:
 README.md                                          |  10 +-
 public/file-viewers-example.json                   |  25 +++
 src/common/config.ts                               |  13 +-
 src/common/formatters.ts                           |   4 +-
 src/common/labels.ts                               |   6 +
 src/components/autocomplete/autocomplete.tsx       |   5 +-
 src/components/context-menu/context-menu.tsx       |   6 +-
 src/components/data-explorer/data-explorer.tsx     |  35 ++--
 src/components/icon/icon.tsx                       |   4 +
 src/components/text-field/text-field.tsx           |   4 +-
 src/index.tsx                                      |  52 +++--
 ...uthorization.ts => api-client-authorization.ts} |  11 +-
 src/models/file-viewers-config.ts                  |  47 +++++
 src/models/link.ts                                 |   6 +-
 src/models/resource.ts                             |   8 +
 src/models/user.ts                                 |  14 +-
 src/routes/route-change-handlers.ts                |  41 +++-
 src/routes/routes.ts                               |  48 ++++-
 .../ancestors-service/ancestors-service.ts         |  21 +-
 .../api-client-authorization-service.ts            |  14 ++
 src/services/api/filter-builder.ts                 |  10 +-
 src/services/auth-service/auth-service.ts          |  21 +-
 .../client-authorizations-service.ts               |  12 --
 .../collection-service/collection-service.ts       |   2 +-
 .../common-service/common-resource-service.ts      | 127 +-----------
 ...ommon-resource-service.ts => common-service.ts} |  87 +++-----
 src/services/favorite-service/favorite-service.ts  |   2 +-
 .../file-viewers-config-service.ts}                |   8 +-
 src/services/groups-service/groups-service.ts      |   3 +-
 .../permission-service/permission-service.ts       |   3 +-
 src/services/project-service/project-service.ts    |   2 +-
 src/services/services.ts                           |   9 +-
 src/services/workflow-service/workflow-service.ts  |  35 ++++
 src/store/advanced-tab/advanced-tab.ts             | 152 +++++++++++++-
 .../api-client-authorizations-actions.ts           |  82 ++++++++
 .../api-client-authorizations-reducer.ts           |  22 ++
 src/store/auth/auth-action-session.ts              |   4 +-
 src/store/auth/auth-action.test.ts                 |   6 +-
 src/store/auth/auth-reducer.test.ts                |   6 +
 src/store/breadcrumbs/breadcrumbs-actions.ts       |  20 ++
 .../collection-panel/collection-panel-action.ts    |  12 ++
 src/store/compute-nodes/compute-nodes-actions.ts   |  23 +--
 .../compute-nodes-middleware-service.ts}           |  46 ++---
 src/store/compute-nodes/compute-nodes-reducer.ts   |  17 --
 src/store/context-menu/context-menu-actions.ts     |  46 +++--
 .../data-explorer-middleware-service.ts            |   2 +-
 src/store/dialog/dialog-actions.ts                 |   3 +-
 src/store/dialog/dialog-reducer.ts                 |  13 +-
 src/store/file-viewers/file-viewers-actions.ts     |  25 +++
 src/store/file-viewers/file-viewers-selectors.ts   |  12 ++
 .../group-details-panel-actions.ts                 | 132 ++++++++++++
 .../group-details-panel-middleware-service.ts      |  79 ++++++++
 src/store/groups-panel/groups-panel-actions.ts     | 225 +++++++++++++++++++++
 .../groups-panel-middleware-service.ts             |  97 +++++++++
 src/store/link-panel/link-panel-actions.ts         |  57 ++++++
 .../link-panel-middleware-service.ts}              |  42 ++--
 src/store/my-account/my-account-panel-actions.ts   |  31 +++
 src/store/navigation/navigation-action.ts          |  27 ++-
 src/store/process-panel/process-panel-actions.ts   |  15 ++
 src/store/processes/process-input-actions.ts       |  11 +-
 src/store/processes/process-update-actions.ts      |   3 +-
 .../project-panel-middleware-service.ts            |  20 +-
 src/store/repositories/repositories-actions.ts     |   2 +-
 .../run-process-panel/run-process-panel-actions.ts |  27 ++-
 .../run-process-panel/run-process-panel-reducer.ts |  12 ++
 .../search-results-middleware-service.ts           |   2 +-
 .../shared-with-me-middleware-service.ts           |   2 +-
 src/store/store.ts                                 |  36 +++-
 src/store/trash-panel/trash-panel-action.ts        |   3 +-
 .../user-panel-middleware-service.ts}              |  28 +--
 src/store/users/users-actions.ts                   | 106 ++++++++++
 .../virtual-machines/virtual-machines-actions.ts   |  34 +++-
 .../virtual-machines/virtual-machines-reducer.ts   |   2 +-
 src/store/workbench/workbench-actions.ts           |  65 +++++-
 .../workflow-panel/workflow-middleware-service.ts  |   4 +-
 src/validators/min-length.tsx                      |  10 +
 src/validators/validators.tsx                      |   6 +
 .../attributes-dialog.tsx                          |  78 +++++++
 .../help-dialog.tsx                                |  66 ++++++
 .../remove-dialog.tsx                              |  10 +-
 ...t.ts => api-client-authorization-action-set.ts} |  11 +-
 .../collection-files-item-action-set.ts            |   4 +
 .../{ssh-key-action-set.ts => group-action-set.ts} |  16 +-
 ...ne-action-set.ts => group-member-action-set.ts} |  16 +-
 .../{ssh-key-action-set.ts => link-action-set.ts}  |  10 +-
 .../context-menu/action-sets/process-action-set.ts |  21 +-
 ...mpute-node-action-set.ts => user-action-set.ts} |  25 ++-
 .../context-menu/actions/file-viewer-actions.tsx   |  81 ++++++++
 src/views-components/context-menu/context-menu.tsx |   7 +-
 .../data-explorer/data-explorer.tsx                |   3 +-
 src/views-components/data-explorer/renderers.tsx   | 192 +++++++++++++++++-
 .../data-explorer/with-resources.tsx               |  27 +++
 .../dialog-create/dialog-user-create.tsx           |  26 +++
 .../dialog-forms/add-group-member-dialog.tsx       |  48 +++++
 .../dialog-forms/create-group-dialog.tsx           |  62 ++++++
 .../dialog-forms/create-user-dialog.ts             |  19 ++
 .../dialog-update/dialog-process-update.tsx        |   3 +-
 .../form-fields/collection-form-fields.tsx         |   6 +-
 .../form-fields/process-form-fields.tsx            |  11 +-
 .../form-fields/user-form-fields.tsx               |  48 +++++
 .../attributes-dialog.tsx                          |  50 +++--
 .../member-attributes-dialog.tsx}                  |  44 ++--
 .../member-remove-dialog.ts}                       |   8 +-
 .../remove-dialog.ts}                              |  11 +-
 .../attributes-dialog.tsx                          |  46 +++--
 .../remove-dialog.tsx                              |  10 +-
 src/views-components/main-app-bar/account-menu.tsx |  28 +--
 src/views-components/main-app-bar/admin-menu.tsx   |  46 +++++
 src/views-components/main-app-bar/help-menu.tsx    |  54 +++--
 src/views-components/main-app-bar/main-app-bar.tsx |   4 +-
 .../main-content-bar/main-content-bar.tsx          |   9 +-
 .../sharing-dialog/people-select.tsx               |   9 +-
 src/views-components/side-panel/side-panel.tsx     |  17 +-
 .../attributes-dialog.tsx                          |  46 +++--
 .../api-client-authorization-panel-root.tsx        | 104 ++++++++++
 .../api-client-authorization-panel.tsx             |  32 +++
 src/views/collection-panel/collection-panel.tsx    |  17 +-
 .../compute-node-panel/compute-node-panel-root.tsx | 167 +++++++++------
 .../compute-node-panel/compute-node-panel.tsx      |  12 +-
 .../group-details-panel/group-details-panel.tsx    | 126 ++++++++++++
 src/views/groups-panel/groups-panel.tsx            | 133 ++++++++++++
 src/views/link-panel/link-panel-root.tsx           |  92 +++++++++
 src/views/link-panel/link-panel.tsx                |  35 ++++
 .../my-account-panel/my-account-panel-root.tsx     | 161 +++++++++++++++
 src/views/my-account-panel/my-account-panel.tsx    |  26 +++
 .../process-panel/process-information-card.tsx     |   9 +-
 src/views/process-panel/process-panel-root.tsx     |   4 +-
 src/views/process-panel/process-panel.tsx          |   5 +-
 .../repositories-panel/repositories-panel.tsx      |   2 +-
 .../run-process-panel/run-process-first-step.tsx   |   4 +-
 .../run-process-panel/run-process-second-step.tsx  |  32 ++-
 .../run-process-panel/workflow-preset-select.tsx   |  68 +++++++
 .../search-results-panel-view.tsx                  |   5 +-
 src/views/trash-panel/trash-panel.tsx              |   6 +-
 src/views/user-panel/user-panel.tsx                | 217 ++++++++++++++++++++
 .../virtual-machine-admin-panel.tsx                | 112 ++++++++++
 ...ne-panel.tsx => virtual-machine-user-panel.tsx} | 133 ++++--------
 src/views/workbench/workbench.tsx                  |  47 ++++-
 .../workflow-panel/workflow-description-card.tsx   |  12 +-
 139 files changed, 4147 insertions(+), 850 deletions(-)
 create mode 100644 public/file-viewers-example.json
 copy src/models/{client-authorization.ts => api-client-authorization.ts} (52%)
 create mode 100644 src/models/file-viewers-config.ts
 create mode 100644 src/services/api-client-authorization-service/api-client-authorization-service.ts
 delete mode 100644 src/services/client-authorizations-service/client-authorizations-service.ts
 copy src/services/common-service/{common-resource-service.ts => common-service.ts} (58%)
 copy src/services/{vocabulary-service/vocabulary-service.ts => file-viewers-config-service/file-viewers-config-service.ts} (62%)
 create mode 100644 src/store/api-client-authorizations/api-client-authorizations-actions.ts
 create mode 100644 src/store/api-client-authorizations/api-client-authorizations-reducer.ts
 copy src/store/{workflow-panel/workflow-middleware-service.ts => compute-nodes/compute-nodes-middleware-service.ts} (61%)
 delete mode 100644 src/store/compute-nodes/compute-nodes-reducer.ts
 create mode 100644 src/store/file-viewers/file-viewers-actions.ts
 create mode 100644 src/store/file-viewers/file-viewers-selectors.ts
 create mode 100644 src/store/group-details-panel/group-details-panel-actions.ts
 create mode 100644 src/store/group-details-panel/group-details-panel-middleware-service.ts
 create mode 100644 src/store/groups-panel/groups-panel-actions.ts
 create mode 100644 src/store/groups-panel/groups-panel-middleware-service.ts
 create mode 100644 src/store/link-panel/link-panel-actions.ts
 copy src/store/{workflow-panel/workflow-middleware-service.ts => link-panel/link-panel-middleware-service.ts} (61%)
 create mode 100644 src/store/my-account/my-account-panel-actions.ts
 copy src/store/{workflow-panel/workflow-middleware-service.ts => users/user-panel-middleware-service.ts} (71%)
 create mode 100644 src/store/users/users-actions.ts
 create mode 100644 src/validators/min-length.tsx
 create mode 100644 src/views-components/api-client-authorizations-dialog/attributes-dialog.tsx
 create mode 100644 src/views-components/api-client-authorizations-dialog/help-dialog.tsx
 copy src/views-components/{ssh-keys-dialog => api-client-authorizations-dialog}/remove-dialog.tsx (59%)
 copy src/views-components/context-menu/action-sets/{compute-node-action-set.ts => api-client-authorization-action-set.ts} (63%)
 copy src/views-components/context-menu/action-sets/{ssh-key-action-set.ts => group-action-set.ts} (54%)
 copy src/views-components/context-menu/action-sets/{virtual-machine-action-set.ts => group-member-action-set.ts} (52%)
 copy src/views-components/context-menu/action-sets/{ssh-key-action-set.ts => link-action-set.ts} (72%)
 copy src/views-components/context-menu/action-sets/{compute-node-action-set.ts => user-action-set.ts} (52%)
 create mode 100644 src/views-components/context-menu/actions/file-viewer-actions.tsx
 create mode 100644 src/views-components/data-explorer/with-resources.tsx
 create mode 100644 src/views-components/dialog-create/dialog-user-create.tsx
 create mode 100644 src/views-components/dialog-forms/add-group-member-dialog.tsx
 create mode 100644 src/views-components/dialog-forms/create-group-dialog.tsx
 create mode 100644 src/views-components/dialog-forms/create-user-dialog.ts
 create mode 100644 src/views-components/form-fields/user-form-fields.tsx
 copy src/views-components/{virtual-machines-dialog => groups-dialog}/attributes-dialog.tsx (56%)
 copy src/views-components/{virtual-machines-dialog/attributes-dialog.tsx => groups-dialog/member-attributes-dialog.tsx} (60%)
 copy src/views-components/{repository-remove-dialog/repository-remove-dialog.ts => groups-dialog/member-remove-dialog.ts} (65%)
 copy src/views-components/{ssh-keys-dialog/remove-dialog.tsx => groups-dialog/remove-dialog.ts} (68%)
 copy src/views-components/{ssh-keys-dialog => links-dialog}/attributes-dialog.tsx (51%)
 copy src/views-components/{ssh-keys-dialog => links-dialog}/remove-dialog.tsx (68%)
 create mode 100644 src/views-components/main-app-bar/admin-menu.tsx
 copy src/views-components/{virtual-machines-dialog => user-dialog}/attributes-dialog.tsx (59%)
 create mode 100644 src/views/api-client-authorization-panel/api-client-authorization-panel-root.tsx
 create mode 100644 src/views/api-client-authorization-panel/api-client-authorization-panel.tsx
 create mode 100644 src/views/group-details-panel/group-details-panel.tsx
 create mode 100644 src/views/groups-panel/groups-panel.tsx
 create mode 100644 src/views/link-panel/link-panel-root.tsx
 create mode 100644 src/views/link-panel/link-panel.tsx
 create mode 100644 src/views/my-account-panel/my-account-panel-root.tsx
 create mode 100644 src/views/my-account-panel/my-account-panel.tsx
 create mode 100644 src/views/run-process-panel/workflow-preset-select.tsx
 create mode 100644 src/views/user-panel/user-panel.tsx
 create mode 100644 src/views/virtual-machine-panel/virtual-machine-admin-panel.tsx
 rename src/views/virtual-machine-panel/{virtual-machine-panel.tsx => virtual-machine-user-panel.tsx} (53%)

       via  f9dde5c781766b8be71d43d0f031c201a0edcfbb (commit)
       via  b6f9b49e6fed67626ae969a6864f45f002fcfd47 (commit)
       via  ec33904efe960ec3e3bddb668d892463171e50bd (commit)
       via  0d0b7399b2e4906e26dbb5035bed033cec0646e9 (commit)
       via  d4b18e45f319eb0885442ab1b64a01683630e38b (commit)
       via  7828a0aa1d5bf4e077a2151380494ebd4e1f1e81 (commit)
       via  80dbbf9199dd7019b22eaadf18112abf1eee1cd7 (commit)
       via  33d05327f82870a6cff480b8d01e89ae75b70786 (commit)
       via  e78eb2de67e896b53f02c656d6ef49e13ff65b62 (commit)
       via  ee63ba213e2e56a57e0cd49f6c7ce9bde5014f53 (commit)
       via  c382494c58a296a0302e774bae8783e03a042174 (commit)
       via  7396826c81a54608d3e7e718b3ca8d5107099df1 (commit)
       via  3c91d92f41c790ceaf8763490820082274061304 (commit)
       via  dbf577587c53e159cf7bd8dfb45dfb64c6ff7bf7 (commit)
       via  1fdf5a6ca607c340e1eb737c4664a5ac7a427d7b (commit)
       via  76a0eb34b5cbd30bf16608b86eec29072a3da3b0 (commit)
       via  1986dc3f720016c2f6eff925469f95032b1f8100 (commit)
       via  83d8f6e889dde0b9c971d794f79f98556b2fdf14 (commit)
       via  47b1e9b2fa97d03438d4ef35f90a5fd0a33bbe34 (commit)
       via  d4b62bc7f7c6e0caf13cf9de78bd2bb9c306e497 (commit)
       via  8634bd88e7bbb8f8d62bbc4016f062fbe30234c8 (commit)
       via  59329caeae17903b97b90b167df5a8122a0c9d95 (commit)
       via  4a8dc9ca8b3c18cf0c21a2537ecef40da5522b67 (commit)
       via  879059e4c20ed40c59a992bce7b1b18bba61d672 (commit)
       via  20aeb9bd5ac0416709beab209b2e33cff88ab753 (commit)
       via  295d62fd5e44819cb55737a86c42db633e097cd8 (commit)
       via  e94e528642f80d57bb6ae5bb717880b2b9adeaca (commit)
       via  7f2af309d0184d3515a1f910bbcb6435f5cd58fb (commit)
       via  a4927ea74470ad483921813d93597b451e3d8e3e (commit)
       via  163d52ede5411167eb4d5786f40b382d992c5126 (commit)
       via  fc43f027e70d0702c88aa61c92dfeed7ac8b793b (commit)
       via  d7a29f892371764b1bff2e6ec64f8011c001b725 (commit)
       via  7cf7cf1a0b0066d044e4648a1311ad7241317128 (commit)
       via  6e0c6489bc761bac498ff4a77dc1bcd777594c67 (commit)
       via  6e92c390c1302fe8d680ebc03c8d048cf7f11fdf (commit)
       via  d8dea15148aaf550018d9f8bf1b273da6bc79f12 (commit)
       via  78e1b6a903071209acc47ba9272ce87a6561e67e (commit)
       via  445787c80c5abc9949133f45c3d9540b426fc046 (commit)
       via  16b3b3bd729ff4fa9fa8d197a3388ece39785a23 (commit)
       via  7ce310947c62c1f514a4c0fe8a367cfff2baf407 (commit)
       via  b1b507febf56cb0622d3599ec68f276d9e0ce3d5 (commit)
       via  7d5095d5324b5d5ee91254f1cfa83f0ef88806cc (commit)
       via  ca091dbfbc7df1a3f81eca2b16925b3225d43138 (commit)
       via  8278f352297c404e9200c92d22dce05b20ad12bc (commit)
       via  413bef83277b0623b319f0c651448b0eaf39048a (commit)
       via  936aa32e065b7f672e27b95262720c2ce8258bf6 (commit)
       via  7e7d0ab455b9e37de66a2d311419454159a4b193 (commit)
       via  506c5d3104812647a34c93690d6d04726edc09d9 (commit)
       via  58e8b67f33be8d000b8ad4f24ee70acbea752e75 (commit)
       via  54b2272cee641887e00c1cc04fd44121048e36b4 (commit)
       via  ce77c6af348f60f332297de2ca9281ade68450e7 (commit)
       via  e4060326613f1a4dfa59c4854078fb4be4f53aea (commit)
       via  e9e0cc24a86e55e7b6421b352800ff29f201a29d (commit)
       via  09f5c7f7b6473444a2d6dc964c2beba6128f319a (commit)
       via  4322da0c140b34c48ecf20e20331111ad27fabaa (commit)
       via  0a9fd3e65e852b2e27f7051736f10fa81a73ba5d (commit)
       via  701e59342c16c23f8ee16c1ef92ee2ca6c416c0a (commit)
       via  f96610d3846dac93bfdfdb3ba329c40f66435281 (commit)
       via  4105d31a5aba13507832d6c86c0154116d857ea5 (commit)
       via  48eb2deb49b06521ab6cf899ac25a544fcd6702e (commit)
       via  1d825abb2c8a4be30a611cd57a5e8b4bfc303d01 (commit)
       via  9f9072365214fbf9d19f0359df90bbf2ab7ae3c9 (commit)
       via  db28e4c12074c0411d907044eb4abf4c462d11b3 (commit)
       via  3a525b4ef49ca90050183713292c95cd244f3123 (commit)
       via  a45ee68505f1a8efdc654d4f200c35ef8d55aff9 (commit)
       via  920ccdc45d7c3a8517b430ab17af53c3fc23cf6d (commit)
       via  8c9cf2d12a513379d13db279b076314b292c037e (commit)
       via  0a901d62940804d2854b2b39d2ea0199fd795ad3 (commit)
       via  18a947dc933f658375a0d03a8822cd85ecfdfce2 (commit)
       via  b384e7ae6054e5041e12ab65301de3200526854a (commit)
       via  454ef1c106b3d738526d65ecfae8db98ad7bebc2 (commit)
       via  090f4825bdd30925a10c6df1b9493df0c2e8f541 (commit)
       via  183874da8b5eb84617e3c81a586c0f7c09946d89 (commit)
       via  877a089738b525098e5e6e63179b6826408f9b5d (commit)
       via  5447edd33bf09dacd51fcaf721576ab2e8f61d66 (commit)
       via  d83c6fd363307c0255b4f3225f57214f5a608199 (commit)
       via  3c5e47e956b63a7caf08a9f25d2c6237e6370b65 (commit)
       via  4223548258ddb3dd7bfb9c520c7c8eb3b5e80f84 (commit)
       via  840b8a123e8161b807e14f5bc8520ffaebf56dd4 (commit)
       via  52a9925b1ab918d66f1508c948e0db8e99568ccf (commit)
       via  31ee65844dcecdae8d2e95535853a9b04a7c4d1c (commit)
       via  13756f84c880e5a6f83a4f416303beb8cd7bc659 (commit)
       via  8b6f5c68fa40ad59092e1290dfd4261f0dfe643f (commit)
       via  4afdbe4d6f060423725d77fa7500d76d8e7e5f04 (commit)
       via  edb6e7b588bc443de1c54782812064f00e6e5b53 (commit)
       via  9fe5431b326d565cb423613f7752a4dad9d9aedd (commit)
       via  1832d4a40997469ae0c2d3e6f2e5a552b834118b (commit)
       via  3dbe57077135d1684407ba6cc2a0d20cfcb33618 (commit)
       via  fc1f170015c5ffd5f4ee5b990d530f3c9782f549 (commit)
       via  e15800c9e0cb809dc212b4133a011cc3f50a7eec (commit)
       via  a5ce24473767588054b48c5355a317989b4b68fa (commit)
       via  00e249f6a7b5e9da3a4b39bfc9d88ec96e928ec0 (commit)
       via  4d2ff0c66175bf47c5643e9500c2cc6d7caf8c8b (commit)
       via  fbeaaaf7f54590fc6fd02b990ee8e4fe1be41817 (commit)
       via  4f09ca588d03cc6e1be52190f902c21a0ae2a850 (commit)
       via  bbfd038f8d53725f154ff139229a74d961792915 (commit)
       via  a8350416b8f225a64aa207c5823e42ede43fd7d0 (commit)
       via  54063448526c6eac346823d6cc66ba7a05f2cce7 (commit)
       via  7a81b9d2c37ceb5add5df8fe9fe48b409d971e37 (commit)
       via  9a29063c1833eb300da899559bc322e7bca50f97 (commit)
       via  0190f22c054d5257f67af66a9a1f1fa84e062fcc (commit)
       via  963621403512fddf0d84b595b41164ba0b552700 (commit)
       via  b2687ded960c6fb9e006bbceb5f93aa685aa70d5 (commit)
       via  ff2d7aa039e4d7a4ab6e77b778f161d6ab45dd2e (commit)
       via  88f16d1a87decacf3dc395126912684ed90dc16f (commit)
       via  3e05c931b42b1b690f43e179aaa9b45c84475ba0 (commit)
       via  74d27e4a497bd9bf66d31e1f4578f63d71fb4d87 (commit)
       via  12531884583ab85a114eed12f5179ed0b5fb8a88 (commit)
       via  9c2991d118f83341e64bc413b48a235fa80f38e2 (commit)
       via  188fed64a7cfe68460f64a874dba3fd280d5d561 (commit)
       via  6c024ce6843e5ad5391fc384792480b751e0c663 (commit)
       via  91fc1bd2a1df91b37755f3453e6e9693baa4ce64 (commit)
       via  2b1802c27fe8eb3664da3378fa7f59761d9ce184 (commit)
       via  4f4f2feaf1ac31946a87290ba4eef3a6b5455f2d (commit)
       via  1b15486e36f96b209a1854c1f33f8330e97f1b94 (commit)
       via  6c0ca05293d2d1bb5b4b0df63f541eb4f75428c3 (commit)
       via  88c4b93c3e4f05afff419374277299d61ac61176 (commit)
       via  6eaf8881f39c83f9073921277f81274425921054 (commit)
       via  4e3cefd4fa42762aac756f3163dfff9047f2e516 (commit)
       via  c0b8c031bf6327c8ed22fb05ec40f3045b5aa1f1 (commit)
       via  860aa7438d52897f646c3482f8656be1193d8123 (commit)
       via  c7b35b9342e953cc3cae862b6958c18589f48037 (commit)
       via  94ca0c19fac51ae89bed3a9bbb2b90545697dfbf (commit)
       via  6c12dcde231f8a6d419a4e154d6906bce944963c (commit)
       via  222a0099d2b8285b8770092f5da01314e0c7de7d (commit)
       via  4c3faee100f2d676bb18dc68f7cf1c4ac25ae50d (commit)
       via  3fdf49aeaf054284ec59e18885e66f798777ada9 (commit)
       via  b8e9a146d964192cc2f0bdc95100644fa53f7ca6 (commit)
       via  bf1d33cba4c15502866dda0ba4385d746033e773 (commit)
       via  6aadd480a93c6b1332cba0d3924362af11412e02 (commit)
       via  6f071fa34ec74d0ba035eb57e102307763d99496 (commit)
       via  f96eb4f60a314f2e5b0a21afd1ab836598d6c91f (commit)
       via  64c8c2628cbeadba5dce7e18e41028108142b766 (commit)
       via  d366e025618106edb2419941a041cd0f4214b245 (commit)
       via  ad5208965b91e020b431cd9d2c1d15ff4b856450 (commit)
       via  e8d0bf057c2f86902b7658ab09d70dc517e5bf2e (commit)
       via  d5d8ac7ffd8b9763ccb9c59ba2d7617d87649419 (commit)
       via  cda10815df30e3bceec728535f426754ef8ff2e8 (commit)
       via  282b04b762cf6366209074333bfd623e3cba58c5 (commit)
       via  3865bd152892a1ad5f85f23d085268837db8c9ee (commit)
       via  7a6743eacc2ef5ce99ceca5acbaff8b00fb7e7d1 (commit)
       via  4a055bfc98a5fc05cc311e2de1ab2213eec5497e (commit)
       via  663ddeefc6a120d6dba213b1392805146d659721 (commit)
       via  0c0daef87be8abcbcc3498d817e453d7336554f8 (commit)
       via  e0effe9fd43b8d7c0d7fcb9aade9b718cf5dddda (commit)
       via  eb8fb03156072ae7d9c289d8d7156fc2d94e40be (commit)
       via  4e1ff9a1613f897f24bc59a981e94d8bf227fd10 (commit)
       via  d19d853e83383a6b75f638be99472aa626a05524 (commit)
       via  fa1f1c301a58d163e452ca9d14d326934a403f17 (commit)
       via  a29cf3418b6c301c0f531cecb7db4c721e7eb014 (commit)
       via  32f8f97903802e58b48ed307669c236750d8ee3e (commit)
       via  a1e2b8ba77e4a7273940a3fc542bc42e282618a7 (commit)
       via  e8e0182d65a74b1a222127eb8b36f31a906b14c8 (commit)
       via  ba9a587ab628caea44d923b34d285a29e83e3456 (commit)
       via  fc3370a1203ae0b83a13ef6a958219cc722cfe75 (commit)
       via  dc95b803fa84b3c9ef7c11a4f81dd0d86077d779 (commit)
       via  b7a4d46fe2b011cdb6e38ed42e9f886fee8290b8 (commit)
       via  4ea2ff188ec745966387ce8bbe14880bfeede863 (commit)
       via  92dd5d32b573b5c90f3ce72dc207f6d0e7f21178 (commit)
      from  95716b93cba4651180021c9a5b752fa10cf5a301 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit f9dde5c781766b8be71d43d0f031c201a0edcfbb
Merge: 95716b93 b6f9b49e
Author: Daniel Kos <daniel.kos at contractors.roche.com>
Date:   Tue Dec 18 10:39:54 2018 +0100

    Merge branch 'origin/master' into 14478-log-in-into-clusters
    
    Feature #14478
    
    # Conflicts:
    #       src/common/config.ts
    #       src/components/text-field/text-field.tsx
    #       src/routes/route-change-handlers.ts
    #       src/routes/routes.ts
    #       src/services/auth-service/auth-service.ts
    #       src/services/common-service/common-resource-service.ts
    #       src/services/services.ts
    #       src/store/auth/auth-action.ts
    #       src/store/navigation/navigation-action.ts
    #       src/store/workbench/workbench-actions.ts
    #       src/validators/validators.tsx
    #       src/views-components/main-app-bar/account-menu.tsx
    #       src/views-components/main-content-bar/main-content-bar.tsx
    #       src/views/workbench/workbench.tsx
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos at contractors.roche.com>

diff --cc src/common/config.ts
index d801c5fa,db67ed8d..3961d5aa
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@@ -126,7 -130,7 +132,8 @@@ interface ConfigJSON 
  const getDefaultConfig = (): ConfigJSON => ({
      API_HOST: process.env.REACT_APP_ARVADOS_API_HOST || "",
      VOCABULARY_URL: "",
+     FILE_VIEWERS_CONFIG_URL: "",
  });
  
 -const getDiscoveryURL = (apiHost: string) => `${window.location.protocol}//${apiHost}/discovery/v1/apis/arvados/v1/rest`;
 +export const DISCOVERY_URL = 'discovery/v1/apis/arvados/v1/rest';
 +const getDiscoveryURL = (apiHost: string) => `${window.location.protocol}//${apiHost}/${DISCOVERY_URL}`;
diff --cc src/components/text-field/text-field.tsx
index 0ebb46bc,627e004d..93c4080f
--- a/src/components/text-field/text-field.tsx
+++ b/src/components/text-field/text-field.tsx
@@@ -25,8 -18,8 +25,8 @@@ const styles: StyleRulesCallback<CssRul
  
  type TextFieldProps = WrappedFieldProps & WithStyles<CssRules>;
  
 -export const TextField = withStyles(styles)((props: TextFieldProps & { 
 -    label?: string, autoFocus?: boolean, required?: boolean, select?: boolean, disabled?: boolean, children: React.ReactNode
 +export const TextField = withStyles(styles)((props: TextFieldProps & {
-     label?: string, autoFocus?: boolean, required?: boolean, select?: boolean, children: React.ReactNode, margin?: Margin, placeholder?: string
++    label?: string, autoFocus?: boolean, required?: boolean, select?: boolean, disabled?: boolean, children: React.ReactNode, margin?: Margin, placeholder?: string
  }) =>
      <MaterialTextField
          helperText={props.meta.touched && props.meta.error}
diff --cc src/routes/route-change-handlers.ts
index 0637a384,03e2a38a..bb88f4a1
--- a/src/routes/route-change-handlers.ts
+++ b/src/routes/route-change-handlers.ts
@@@ -26,12 -29,23 +29,24 @@@ const handleLocationChange = (store: Ro
      const searchResultsMatch = Routes.matchSearchResultsRoute(pathname);
      const sharedWithMeMatch = Routes.matchSharedWithMeRoute(pathname);
      const runProcessMatch = Routes.matchRunProcessRoute(pathname);
-     const virtualMachineMatch = Routes.matchVirtualMachineRoute(pathname);
+     const virtualMachineUserMatch = Routes.matchUserVirtualMachineRoute(pathname);
+     const virtualMachineAdminMatch = Routes.matchAdminVirtualMachineRoute(pathname);
      const workflowMatch = Routes.matchWorkflowRoute(pathname);
-     const sshKeysMatch = Routes.matchSshKeysRoute(pathname);
+     const sshKeysUserMatch = Routes.matchSshKeysUserRoute(pathname);
+     const sshKeysAdminMatch = Routes.matchSshKeysAdminRoute(pathname);
 +    const siteManagerMatch = Routes.matchSiteManagerRoute(pathname);
      const keepServicesMatch = Routes.matchKeepServicesRoute(pathname);
      const computeNodesMatch = Routes.matchComputeNodesRoute(pathname);
+     const apiClientAuthorizationsMatch = Routes.matchApiClientAuthorizationsRoute(pathname);
+     const myAccountMatch = Routes.matchMyAccountRoute(pathname);
+     const userMatch = Routes.matchUsersRoute(pathname);
+     const groupsMatch = Routes.matchGroupsRoute(pathname);
+     const groupDetailsMatch = Routes.matchGroupDetailsRoute(pathname);
+     const linksMatch = Routes.matchLinksRoute(pathname);
+ 
+     store.dispatch(dialogActions.CLOSE_ALL_DIALOGS());
+     store.dispatch(contextMenuActions.CLOSE_CONTEXT_MENU());
+     store.dispatch(searchBarActions.CLOSE_SEARCH_VIEW());
  
      if (projectMatch) {
          store.dispatch(WorkbenchActions.loadProject(projectMatch.params.id));
@@@ -55,14 -69,16 +70,18 @@@
          store.dispatch(WorkbenchActions.loadWorkflow);
      } else if (searchResultsMatch) {
          store.dispatch(WorkbenchActions.loadSearchResults);
-     } else if (virtualMachineMatch) {
+     } else if (virtualMachineUserMatch) {
+         store.dispatch(WorkbenchActions.loadVirtualMachines);
+     } else if (virtualMachineAdminMatch) {
          store.dispatch(WorkbenchActions.loadVirtualMachines);
-     } else if(repositoryMatch) {
+     } else if (repositoryMatch) {
          store.dispatch(WorkbenchActions.loadRepositories);
-     } else if (sshKeysMatch) {
+     } else if (sshKeysUserMatch) {
+         store.dispatch(WorkbenchActions.loadSshKeys);
+     } else if (sshKeysAdminMatch) {
          store.dispatch(WorkbenchActions.loadSshKeys);
 +    } else if (siteManagerMatch) {
 +        store.dispatch(WorkbenchActions.loadSiteManager);
      } else if (keepServicesMatch) {
          store.dispatch(WorkbenchActions.loadKeepServices);
      } else if (computeNodesMatch) {
diff --cc src/routes/routes.ts
index b5cb0aca,661a065e..b1da9496
--- a/src/routes/routes.ts
+++ b/src/routes/routes.ts
@@@ -19,13 -19,20 +19,21 @@@ export const Routes = 
      REPOSITORIES: '/repositories',
      SHARED_WITH_ME: '/shared-with-me',
      RUN_PROCESS: '/run-process',
-     VIRTUAL_MACHINES: '/virtual-machines',
+     VIRTUAL_MACHINES_ADMIN: '/virtual-machines-admin',
+     VIRTUAL_MACHINES_USER: '/virtual-machines-user',
      WORKFLOWS: '/workflows',
      SEARCH_RESULTS: '/search-results',
-     SSH_KEYS: `/ssh-keys`,
+     SSH_KEYS_ADMIN: `/ssh-keys-admin`,
+     SSH_KEYS_USER: `/ssh-keys-user`,
 +    SITE_MANAGER: `/site-manager`,
+     MY_ACCOUNT: '/my-account',
      KEEP_SERVICES: `/keep-services`,
-     COMPUTE_NODES: `/nodes`
+     COMPUTE_NODES: `/nodes`,
+     USERS: '/users',
+     API_CLIENT_AUTHORIZATIONS: `/api_client_authorizations`,
+     GROUPS: '/groups',
+     GROUP_DETAILS: `/group/:id(${RESOURCE_UUID_PATTERN})`,
+     LINKS: '/links'
  };
  
  export const getResourceUrl = (uuid: string) => {
@@@ -89,12 -101,15 +102,18 @@@ export const matchAdminVirtualMachineRo
  export const matchRepositoriesRoute = (route: string) =>
      matchPath<ResourceRouteParams>(route, { path: Routes.REPOSITORIES });
  
- export const matchSshKeysRoute = (route: string) =>
-     matchPath(route, { path: Routes.SSH_KEYS });
+ export const matchSshKeysUserRoute = (route: string) =>
+     matchPath(route, { path: Routes.SSH_KEYS_USER });
+ 
+ export const matchSshKeysAdminRoute = (route: string) =>
+     matchPath(route, { path: Routes.SSH_KEYS_ADMIN });
  
 +export const matchSiteManagerRoute = (route: string) =>
 +    matchPath(route, { path: Routes.SITE_MANAGER });
 +
+ export const matchMyAccountRoute = (route: string) =>
+     matchPath(route, { path: Routes.MY_ACCOUNT });
+ 
  export const matchKeepServicesRoute = (route: string) =>
      matchPath(route, { path: Routes.KEEP_SERVICES });
  
diff --cc src/services/auth-service/auth-service.ts
index 1492ef1c,22c9dcd6..8601e208
--- a/src/services/auth-service/auth-service.ts
+++ b/src/services/auth-service/auth-service.ts
@@@ -2,7 -2,7 +2,7 @@@
  //
  // SPDX-License-Identifier: AGPL-3.0
  
- import { getUserFullname, User } from "~/models/user";
 -import { User, UserPrefs } from "~/models/user";
++import { getUserFullname, User, UserPrefs } from "~/models/user";
  import { AxiosInstance } from "axios";
  import { ApiActions } from "~/services/api/api-actions";
  import * as uuid from "uuid/v4";
diff --cc src/store/auth/auth-action-session.ts
index 4a6f56f9,00000000..83e98e96
mode 100644,000000..100644
--- a/src/store/auth/auth-action-session.ts
+++ b/src/store/auth/auth-action-session.ts
@@@ -1,206 -1,0 +1,208 @@@
 +// Copyright (C) The Arvados Authors. All rights reserved.
 +//
 +// SPDX-License-Identifier: AGPL-3.0
 +
 +import { Dispatch } from "redux";
 +import { setBreadcrumbs } from "~/store/breadcrumbs/breadcrumbs-actions";
 +import { RootState } from "~/store/store";
 +import { ServiceRepository } from "~/services/services";
 +import Axios from "axios";
 +import { getUserFullname, User } from "~/models/user";
 +import { authActions } from "~/store/auth/auth-action";
 +import { Config, DISCOVERY_URL } from "~/common/config";
 +import { Session, SessionStatus } from "~/models/session";
 +import { progressIndicatorActions } from "~/store/progress-indicator/progress-indicator-actions";
 +import { UserDetailsResponse } from "~/services/auth-service/auth-service";
 +import * as jsSHA from "jssha";
 +
 +const getRemoteHostBaseUrl = async (remoteHost: string): Promise<string | null> => {
 +    let url = remoteHost;
 +    if (url.indexOf('://') < 0) {
 +        url = 'https://' + url;
 +    }
 +    const origin = new URL(url).origin;
 +    let baseUrl: string | null = null;
 +
 +    try {
 +        const resp = await Axios.get<Config>(`${origin}/${DISCOVERY_URL}`);
 +        baseUrl = resp.data.baseUrl;
 +    } catch (err) {
 +        try {
 +            const resp = await Axios.get<any>(`${origin}/status.json`);
 +            baseUrl = resp.data.apiBaseURL;
 +        } catch (err) {
 +        }
 +    }
 +
 +    if (baseUrl && baseUrl[baseUrl.length - 1] === '/') {
 +        baseUrl = baseUrl.substr(0, baseUrl.length - 1);
 +    }
 +
 +    return baseUrl;
 +};
 +
 +const getUserDetails = async (baseUrl: string, token: string): Promise<UserDetailsResponse> => {
 +    const resp = await Axios.get<UserDetailsResponse>(`${baseUrl}/users/current`, {
 +        headers: {
 +            Authorization: `OAuth2 ${token}`
 +        }
 +    });
 +    return resp.data;
 +};
 +
 +const getTokenUuid = async (baseUrl: string, token: string): Promise<string> => {
 +    if (token.startsWith("v2/")) {
 +        const uuid = token.split("/")[1];
 +        return Promise.resolve(uuid);
 +    }
 +
 +    const resp = await Axios.get(`${baseUrl}/api_client_authorizations`, {
 +        headers: {
 +            Authorization: `OAuth2 ${token}`
 +        },
 +        data: {
 +            filters: JSON.stringify([['api_token', '=', token]])
 +        }
 +    });
 +
 +    return resp.data.items[0].uuid;
 +};
 +
 +const getSaltedToken = (clusterId: string, tokenUuid: string, token: string) => {
 +    const shaObj = new jsSHA("SHA-1", "TEXT");
 +    let secret = token;
 +    if (token.startsWith("v2/")) {
 +        secret = token.split("/")[2];
 +    }
 +    shaObj.setHMACKey(secret, "TEXT");
 +    shaObj.update(clusterId);
 +    const hmac = shaObj.getHMAC("HEX");
 +    return `v2/${tokenUuid}/${hmac}`;
 +};
 +
 +const clusterLogin = async (clusterId: string, baseUrl: string, activeSession: Session): Promise<{user: User, token: string}> => {
 +    const tokenUuid = await getTokenUuid(activeSession.baseUrl, activeSession.token);
 +    const saltedToken = getSaltedToken(clusterId, tokenUuid, activeSession.token);
 +    const user = await getUserDetails(baseUrl, saltedToken);
 +    return {
 +        user: {
 +            firstName: user.first_name,
 +            lastName: user.last_name,
 +            uuid: user.uuid,
 +            ownerUuid: user.owner_uuid,
 +            email: user.email,
-             isAdmin: user.is_admin
++            isAdmin: user.is_admin,
++            identityUrl: user.identity_url,
++            prefs: user.prefs
 +        },
 +        token: saltedToken
 +    };
 +};
 +
 +const getActiveSession = (sessions: Session[]): Session | undefined => sessions.find(s => s.active);
 +
 +export const validateCluster = async (remoteHost: string, clusterId: string, activeSession: Session): Promise<{ user: User; token: string, baseUrl: string }> => {
 +    const baseUrl = await getRemoteHostBaseUrl(remoteHost);
 +    if (!baseUrl) {
 +        return Promise.reject(`Could not find base url for ${remoteHost}`);
 +    }
 +    const { user, token } = await clusterLogin(clusterId, baseUrl, activeSession);
 +    return { baseUrl, user, token };
 +};
 +
 +export const validateSession = (session: Session, activeSession: Session) =>
 +    async (dispatch: Dispatch): Promise<Session> => {
 +        dispatch(authActions.UPDATE_SESSION({ ...session, status: SessionStatus.BEING_VALIDATED }));
 +        session.loggedIn = false;
 +        try {
 +            const { baseUrl, user, token } = await validateCluster(session.remoteHost, session.clusterId, activeSession);
 +            session.baseUrl = baseUrl;
 +            session.token = token;
 +            session.email = user.email;
 +            session.username = getUserFullname(user);
 +            session.loggedIn = true;
 +        } catch {
 +            session.loggedIn = false;
 +        } finally {
 +            session.status = SessionStatus.VALIDATED;
 +            dispatch(authActions.UPDATE_SESSION(session));
 +        }
 +        return session;
 +    };
 +
 +export const validateSessions = () =>
 +    async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
 +        const sessions = getState().auth.sessions;
 +        const activeSession = getActiveSession(sessions);
 +        if (activeSession) {
 +            dispatch(progressIndicatorActions.START_WORKING("sessionsValidation"));
 +            for (const session of sessions) {
 +                if (session.status === SessionStatus.INVALIDATED) {
 +                    await dispatch(validateSession(session, activeSession));
 +                }
 +            }
 +            services.authService.saveSessions(sessions);
 +            dispatch(progressIndicatorActions.STOP_WORKING("sessionsValidation"));
 +        }
 +    };
 +
 +export const addSession = (remoteHost: string) =>
 +    async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
 +        const sessions = getState().auth.sessions;
 +        const activeSession = getActiveSession(sessions);
 +        if (activeSession) {
 +            const clusterId = remoteHost.match(/^(\w+)\./)![1];
 +            if (sessions.find(s => s.clusterId === clusterId)) {
 +                return Promise.reject("Cluster already exists");
 +            }
 +            try {
 +                const { baseUrl, user, token } = await validateCluster(remoteHost, clusterId, activeSession);
 +                const session = {
 +                    loggedIn: true,
 +                    status: SessionStatus.VALIDATED,
 +                    active: false,
 +                    email: user.email,
 +                    username: getUserFullname(user),
 +                    remoteHost,
 +                    baseUrl,
 +                    clusterId,
 +                    token
 +                };
 +
 +                dispatch(authActions.ADD_SESSION(session));
 +                services.authService.saveSessions(getState().auth.sessions);
 +
 +                return session;
 +            } catch (e) {
 +            }
 +        }
 +        return Promise.reject("Could not validate cluster");
 +    };
 +
 +export const toggleSession = (session: Session) =>
 +    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
 +        let s = { ...session };
 +
 +        if (session.loggedIn) {
 +            s.loggedIn = false;
 +        } else {
 +            const sessions = getState().auth.sessions;
 +            const activeSession = getActiveSession(sessions);
 +            if (activeSession) {
 +                s = await dispatch<any>(validateSession(s, activeSession)) as Session;
 +            }
 +        }
 +
 +        dispatch(authActions.UPDATE_SESSION(s));
 +        services.authService.saveSessions(getState().auth.sessions);
 +    };
 +
 +export const loadSiteManagerPanel = () =>
 +    async (dispatch: Dispatch<any>) => {
 +        try {
 +            dispatch(setBreadcrumbs([{ label: 'Site Manager'}]));
 +            dispatch(validateSessions());
 +        } catch (e) {
 +            return;
 +        }
 +    };
diff --cc src/store/navigation/navigation-action.ts
index 8e3929d9,c53c55e8..f610eb5e
--- a/src/store/navigation/navigation-action.ts
+++ b/src/store/navigation/navigation-action.ts
@@@ -66,10 -73,12 +73,14 @@@ export const navigateToAdminVirtualMach
  
  export const navigateToRepositories = push(Routes.REPOSITORIES);
  
- export const navigateToSshKeys= push(Routes.SSH_KEYS);
+ export const navigateToSshKeysAdmin= push(Routes.SSH_KEYS_ADMIN);
+ 
+ export const navigateToSshKeysUser= push(Routes.SSH_KEYS_USER);
  
 +export const navigateToSiteManager= push(Routes.SITE_MANAGER);
 +
+ export const navigateToMyAccount = push(Routes.MY_ACCOUNT);
+ 
  export const navigateToKeepServices = push(Routes.KEEP_SERVICES);
  
  export const navigateToComputeNodes = push(Routes.COMPUTE_NODES);
diff --cc src/store/workbench/workbench-actions.ts
index fdef38c4,5e9dc285..46ab1f59
--- a/src/store/workbench/workbench-actions.ts
+++ b/src/store/workbench/workbench-actions.ts
@@@ -39,8 -39,8 +39,9 @@@ import { sharedWithMePanelActions } fro
  import { loadSharedWithMePanel } from '~/store/shared-with-me-panel/shared-with-me-panel-actions';
  import { CopyFormDialogData } from '~/store/copy-dialog/copy-dialog';
  import { loadWorkflowPanel, workflowPanelActions } from '~/store/workflow-panel/workflow-panel-actions';
 -import { loadSshKeysPanel } from '~/store/auth/auth-action';
 +import { loadSshKeysPanel } from '~/store/auth/auth-action-ssh';
+ import { loadMyAccountPanel } from '~/store/my-account/my-account-panel-actions';
 +import { loadSiteManagerPanel } from '~/store/auth/auth-action-session';
  import { workflowPanelColumns } from '~/views/workflow-panel/workflow-panel-view';
  import { progressIndicatorActions } from '~/store/progress-indicator/progress-indicator-actions';
  import { getProgressIndicator } from '~/store/progress-indicator/progress-indicator-reducer';
@@@ -413,9 -435,9 +436,14 @@@ export const loadSshKeys = handleFirstT
          await dispatch(loadSshKeysPanel());
      });
  
 +export const loadSiteManager = handleFirstTimeLoad(
-     async (dispatch: Dispatch<any>) => {
-         await dispatch(loadSiteManagerPanel());
++async (dispatch: Dispatch<any>) => {
++    await dispatch(loadSiteManagerPanel());
++});
++
+ export const loadMyAccount = handleFirstTimeLoad(
+     (dispatch: Dispatch<any>) => {
+         dispatch(loadMyAccountPanel());
      });
  
  export const loadKeepServices = handleFirstTimeLoad(
diff --cc src/validators/validators.tsx
index 06f46219,9bc76419..acef9744
--- a/src/validators/validators.tsx
+++ b/src/validators/validators.tsx
@@@ -28,4 -31,4 +32,6 @@@ export const USER_LENGTH_VALIDATION = [
  export const SSH_KEY_PUBLIC_VALIDATION = [require, isRsaKey, maxLength(1024)];
  export const SSH_KEY_NAME_VALIDATION = [require, maxLength(255)];
  
 +export const SITE_MANAGER_REMOTE_HOST_VALIDATION = [require, isRemoteHost, maxLength(255)];
++
+ export const MY_ACCOUNT_VALIDATION = [require];
diff --cc src/views-components/main-app-bar/account-menu.tsx
index b71c92cb,53a5753d..6c1e46c5
--- a/src/views-components/main-app-bar/account-menu.tsx
+++ b/src/views-components/main-app-bar/account-menu.tsx
@@@ -11,14 -11,9 +11,13 @@@ import { DispatchProp, connect } from '
  import { logout } from '~/store/auth/auth-action';
  import { RootState } from "~/store/store";
  import { openCurrentTokenDialog } from '~/store/current-token-dialog/current-token-dialog-actions';
 -import { navigateToSshKeysUser, navigateToMyAccount } from '~/store/navigation/navigation-action';
 +import { openRepositoriesPanel } from "~/store/repositories/repositories-actions";
 +import {
-     navigateToSshKeys,
-     navigateToKeepServices,
-     navigateToComputeNodes,
-     navigateToSiteManager
++    navigateToSiteManager,
++    navigateToSshKeysUser,
++    navigateToMyAccount
 +} from '~/store/navigation/navigation-action';
- import { openVirtualMachines } from "~/store/virtual-machines/virtual-machines-actions";
+ import { openUserVirtualMachines } from "~/store/virtual-machines/virtual-machines-actions";
 -import { openRepositoriesPanel } from '~/store/repositories/repositories-actions';
  
  interface AccountMenuProps {
      user?: User;
@@@ -38,14 -36,11 +40,12 @@@ export const AccountMenu = connect(mapS
                  <MenuItem>
                      {getUserFullname(user)}
                  </MenuItem>
-                 <MenuItem onClick={() => dispatch(openVirtualMachines())}>Virtual Machines</MenuItem>
-                 <MenuItem onClick={() => dispatch(openRepositoriesPanel())}>Repositories</MenuItem>
+                 <MenuItem onClick={() => dispatch(openUserVirtualMachines())}>Virtual Machines</MenuItem>
+                 {!user.isAdmin && <MenuItem onClick={() => dispatch(openRepositoriesPanel())}>Repositories</MenuItem>}
                  <MenuItem onClick={() => dispatch(openCurrentTokenDialog)}>Current token</MenuItem>
-                 <MenuItem onClick={() => dispatch(navigateToSshKeys)}>Ssh Keys</MenuItem>
+                 <MenuItem onClick={() => dispatch(navigateToSshKeysUser)}>Ssh Keys</MenuItem>
 +                <MenuItem onClick={() => dispatch(navigateToSiteManager)}>Site Manager</MenuItem>
-                 { user.isAdmin && <MenuItem onClick={() => dispatch(navigateToKeepServices)}>Keep Services</MenuItem> }
-                 { user.isAdmin && <MenuItem onClick={() => dispatch(navigateToComputeNodes)}>Compute Nodes</MenuItem> }
-                 <MenuItem>My account</MenuItem>
+                 <MenuItem onClick={() => dispatch(navigateToMyAccount)}>My account</MenuItem>
                  <MenuItem onClick={() => dispatch(logout())}>Logout</MenuItem>
              </DropdownMenu>
              : null);
diff --cc src/views-components/main-content-bar/main-content-bar.tsx
index 8b8f9891,3806b524..c0014d00
--- a/src/views-components/main-content-bar/main-content-bar.tsx
+++ b/src/views-components/main-content-bar/main-content-bar.tsx
@@@ -18,10 -18,12 +18,13 @@@ interface MainContentBarProps 
  
  const isButtonVisible = ({ router }: RootState) => {
      const pathname = router.location ? router.location.pathname : '';
-     return !Routes.matchWorkflowRoute(pathname) && !Routes.matchVirtualMachineRoute(pathname) &&
-         !Routes.matchRepositoriesRoute(pathname) && !Routes.matchSshKeysRoute(pathname) &&
+     return !Routes.matchWorkflowRoute(pathname) && !Routes.matchUserVirtualMachineRoute(pathname) &&
+         !Routes.matchAdminVirtualMachineRoute(pathname) && !Routes.matchRepositoriesRoute(pathname) &&
+         !Routes.matchSshKeysAdminRoute(pathname) && !Routes.matchSshKeysUserRoute(pathname) &&
++        !Routes.matchSiteManagerRoute(pathname) &&
          !Routes.matchKeepServicesRoute(pathname) && !Routes.matchComputeNodesRoute(pathname) &&
-         !Routes.matchSiteManagerRoute(pathname);
+         !Routes.matchApiClientAuthorizationsRoute(pathname) && !Routes.matchUsersRoute(pathname) &&
+         !Routes.matchMyAccountRoute(pathname) && !Routes.matchLinksRoute(pathname);
  };
  
  export const MainContentBar = connect((state: RootState) => ({
diff --cc src/views/workbench/workbench.tsx
index af2325bf,bff328e8..90b2dad0
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@@ -45,7 -45,7 +45,8 @@@ import SplitterLayout from 'react-split
  import { WorkflowPanel } from '~/views/workflow-panel/workflow-panel';
  import { SearchResultsPanel } from '~/views/search-results-panel/search-results-panel';
  import { SshKeyPanel } from '~/views/ssh-key-panel/ssh-key-panel';
 +import { SiteManagerPanel } from "~/views/site-manager-panel/site-manager-panel";
+ import { MyAccountPanel } from '~/views/my-account-panel/my-account-panel';
  import { SharingDialog } from '~/views-components/sharing-dialog/sharing-dialog';
  import { AdvancedTabDialog } from '~/views-components/advanced-tab-dialog/advanced-tab-dialog';
  import { ProcessInputDialog } from '~/views-components/process-input-dialog/process-input-dialog';
@@@ -137,12 -156,19 +157,20 @@@ export const WorkbenchPanel 
                                  <Route path={Routes.RUN_PROCESS} component={RunProcessPanel} />
                                  <Route path={Routes.WORKFLOWS} component={WorkflowPanel} />
                                  <Route path={Routes.SEARCH_RESULTS} component={SearchResultsPanel} />
-                                 <Route path={Routes.VIRTUAL_MACHINES} component={VirtualMachinePanel} />
+                                 <Route path={Routes.VIRTUAL_MACHINES_USER} component={VirtualMachineUserPanel} />
+                                 <Route path={Routes.VIRTUAL_MACHINES_ADMIN} component={VirtualMachineAdminPanel} />
                                  <Route path={Routes.REPOSITORIES} component={RepositoriesPanel} />
-                                 <Route path={Routes.SSH_KEYS} component={SshKeyPanel} />
+                                 <Route path={Routes.SSH_KEYS_USER} component={SshKeyPanel} />
+                                 <Route path={Routes.SSH_KEYS_ADMIN} component={SshKeyPanel} />
 +                                <Route path={Routes.SITE_MANAGER} component={SiteManagerPanel} />
                                  <Route path={Routes.KEEP_SERVICES} component={KeepServicePanel} />
+                                 <Route path={Routes.USERS} component={UserPanel} />
                                  <Route path={Routes.COMPUTE_NODES} component={ComputeNodePanel} />
+                                 <Route path={Routes.API_CLIENT_AUTHORIZATIONS} component={ApiClientAuthorizationPanel} />
+                                 <Route path={Routes.MY_ACCOUNT} component={MyAccountPanel} />
+                                 <Route path={Routes.GROUPS} component={GroupsPanel} />
+                                 <Route path={Routes.GROUP_DETAILS} component={GroupDetailsPanel} />
+                                 <Route path={Routes.LINKS} component={LinkPanel} />
                              </Switch>
                          </Grid>
                      </Grid>
@@@ -190,6 -228,7 +230,7 @@@
              <UpdateCollectionDialog />
              <UpdateProcessDialog />
              <UpdateProjectDialog />
+             <UserAttributesDialog />
              <VirtualMachineAttributesDialog />
          </Grid>
 -    );
 +    );

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list