feat: initial commit
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
export class AbstractResourcesTable extends React.Component {
|
||||
hasPermissions(row) {
|
||||
return this.state.permissions.has(row) && this.state.permissions.get(row).length > 0;
|
||||
}
|
||||
|
||||
firstUser(row) {
|
||||
if (!this.hasPermissions(row)) return 'ERROR!!!!'; // should never happen
|
||||
|
||||
return this.state.permissions.get(row)[0].username;
|
||||
}
|
||||
|
||||
numOthers(row) {
|
||||
if (!this.hasPermissions(row)) return -1; // should never happen
|
||||
|
||||
return this.state.permissions.get(row).length - 1;
|
||||
}
|
||||
|
||||
sharedWithUsersMessage(row) {
|
||||
if (!this.hasPermissions(row)) return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "resourceNotShared"
|
||||
}));
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "resourceSharedWith"
|
||||
}, /*#__PURE__*/React.createElement("strong", null, this.firstUser(row))), this.numOthers(row) > 0 && /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "and"
|
||||
}, /*#__PURE__*/React.createElement("strong", null, this.numOthers(row))), ".");
|
||||
}
|
||||
|
||||
getClientName(client) {
|
||||
if (client.hasOwnProperty('name') && client.name !== null && client.name !== '') {
|
||||
return Msg.localize(client.name);
|
||||
} else {
|
||||
return client.clientId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=AbstractResourceTable.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/app/content/my-resources-page/AbstractResourceTable.tsx"],"names":["React","Msg","AbstractResourcesTable","Component","hasPermissions","row","state","permissions","has","get","length","firstUser","username","numOthers","sharedWithUsersMessage","getClientName","client","hasOwnProperty","name","localize","clientId"],"mappings":"AAAA,OAAO,KAAKA,KAAZ;AAEA,SAASC,GAAT;AAUA,OAAO,MAAeC,sBAAf,SAA6EF,KAAK,CAACG,SAAnF,CAAqH;AAEhHC,EAAAA,cAAc,CAACC,GAAD,EAAuB;AAC7C,WAAQ,KAAKC,KAAL,CAAWC,WAAX,CAAuBC,GAAvB,CAA2BH,GAA3B,CAAD,IAAsC,KAAKC,KAAL,CAAWC,WAAX,CAAuBE,GAAvB,CAA2BJ,GAA3B,EAAiCK,MAAjC,GAA0C,CAAvF;AACD;;AAEOC,EAAAA,SAAS,CAACN,GAAD,EAAsB;AACrC,QAAI,CAAC,KAAKD,cAAL,CAAoBC,GAApB,CAAL,EAA+B,OAAO,WAAP,CADM,CACc;;AAEnD,WAAO,KAAKC,KAAL,CAAWC,WAAX,CAAuBE,GAAvB,CAA2BJ,GAA3B,EAAiC,CAAjC,EAAoCO,QAA3C;AACD;;AAESC,EAAAA,SAAS,CAACR,GAAD,EAAsB;AACvC,QAAI,CAAC,KAAKD,cAAL,CAAoBC,GAApB,CAAL,EAA+B,OAAO,CAAC,CAAR,CADQ,CACG;;AAE1C,WAAO,KAAKC,KAAL,CAAWC,WAAX,CAAuBE,GAAvB,CAA2BJ,GAA3B,EAAiCK,MAAjC,GAA0C,CAAjD;AACD;;AAEMI,EAAAA,sBAAsB,CAACT,GAAD,EAA+B;AAC1D,QAAI,CAAC,KAAKD,cAAL,CAAoBC,GAApB,CAAL,EAA+B,oBAAQ,oBAAC,KAAD,CAAO,QAAP,qBAAgB,oBAAC,GAAD;AAAK,MAAA,MAAM,EAAC;AAAZ,MAAhB,CAAR;AAE/B,wBACE,oBAAC,KAAD,CAAO,QAAP,qBACE,oBAAC,GAAD;AAAK,MAAA,MAAM,EAAC;AAAZ,oBACE,oCAAS,KAAKM,SAAL,CAAeN,GAAf,CAAT,CADF,CADF,EAIG,KAAKQ,SAAL,CAAeR,GAAf,IAAsB,CAAtB,iBAA2B,oBAAC,GAAD;AAAK,MAAA,MAAM,EAAC;AAAZ,oBAC1B,oCAAS,KAAKQ,SAAL,CAAeR,GAAf,CAAT,CAD0B,CAJ9B,MADF;AAUD;;AAESU,EAAAA,aAAa,CAACC,MAAD,EAAyB;AAC9C,QAAIA,MAAM,CAACC,cAAP,CAAsB,MAAtB,KAAiCD,MAAM,CAACE,IAAP,KAAgB,IAAjD,IAAyDF,MAAM,CAACE,IAAP,KAAgB,EAA7E,EAAiF;AAC/E,aAAOjB,GAAG,CAACkB,QAAJ,CAAaH,MAAM,CAACE,IAApB,CAAP;AACD,KAFD,MAEO;AACL,aAAOF,MAAM,CAACI,QAAd;AACD;AACF;;AAvCyH","sourcesContent":["import * as React from 'react';\nimport { Permission, PaginatedResources, Client } from './resource-model';\nimport { Msg } from '../../widgets/Msg';\n\nexport interface ResourcesTableProps {\n resources: PaginatedResources;\n}\n\nexport interface ResourcesTableState {\n permissions: Map<number, Permission[]>;\n}\n\nexport abstract class AbstractResourcesTable<S extends ResourcesTableState> extends React.Component<ResourcesTableProps, S> {\n\n protected hasPermissions(row: number): boolean {\n return (this.state.permissions.has(row)) && (this.state.permissions.get(row)!.length > 0);\n }\n\n private firstUser(row: number): string {\n if (!this.hasPermissions(row)) return 'ERROR!!!!'; // should never happen\n\n return this.state.permissions.get(row)![0].username;\n }\n\n protected numOthers(row: number): number {\n if (!this.hasPermissions(row)) return -1; // should never happen\n\n return this.state.permissions.get(row)!.length - 1;\n }\n\n public sharedWithUsersMessage(row: number): React.ReactNode {\n if (!this.hasPermissions(row)) return (<React.Fragment><Msg msgKey='resourceNotShared' /></React.Fragment>);\n\n return (\n <React.Fragment>\n <Msg msgKey='resourceSharedWith'>\n <strong>{this.firstUser(row)}</strong>\n </Msg>\n {this.numOthers(row) > 0 && <Msg msgKey='and'>\n <strong>{this.numOthers(row)}</strong>\n </Msg>}.\n </React.Fragment>\n );\n }\n\n protected getClientName(client: Client): string {\n if (client.hasOwnProperty('name') && client.name !== null && client.name !== '') {\n return Msg.localize(client.name!);\n } else {\n return client.clientId;\n }\n }\n}\n"],"file":"AbstractResourceTable.js"}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
/*
|
||||
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import { Button, Modal, Form, FormGroup, TextInput, InputGroup, ModalVariant } from "../../../../common/keycloak/web_modules/@patternfly/react-core.js";
|
||||
import { OkIcon } from "../../../../common/keycloak/web_modules/@patternfly/react-icons.js";
|
||||
import { Scope } from "./resource-model.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
import { AccountServiceContext } from "../../account-service/AccountServiceContext.js";
|
||||
import { ContentAlert } from "../ContentAlert.js";
|
||||
import { PermissionSelect } from "./PermissionSelect.js";
|
||||
export class EditTheResource extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
_defineProperty(this, "context", void 0);
|
||||
|
||||
_defineProperty(this, "handleToggleDialog", () => {
|
||||
if (this.state.isOpen) {
|
||||
this.setState({
|
||||
isOpen: false
|
||||
});
|
||||
this.props.onClose();
|
||||
} else {
|
||||
this.clearState();
|
||||
this.setState({
|
||||
isOpen: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "updateChanged", row => {
|
||||
const changed = this.state.changed;
|
||||
changed[row] = !changed[row];
|
||||
this.setState({
|
||||
changed
|
||||
});
|
||||
});
|
||||
|
||||
this.context = context;
|
||||
this.state = {
|
||||
changed: [],
|
||||
isOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
clearState() {
|
||||
this.setState({});
|
||||
}
|
||||
|
||||
async savePermission(permission) {
|
||||
await this.context.doPut(`/resources/${this.props.resource._id}/permissions`, [permission]);
|
||||
ContentAlert.success(Msg.localize('updateSuccess'));
|
||||
}
|
||||
|
||||
render() {
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, this.props.children(this.handleToggleDialog), /*#__PURE__*/React.createElement(Modal, {
|
||||
title: 'Edit the resource - ' + this.props.resource.name,
|
||||
variant: ModalVariant.large,
|
||||
isOpen: this.state.isOpen,
|
||||
onClose: this.handleToggleDialog,
|
||||
actions: [/*#__PURE__*/React.createElement(Button, {
|
||||
key: "done",
|
||||
variant: "link",
|
||||
id: "done",
|
||||
onClick: this.handleToggleDialog
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "done"
|
||||
}))]
|
||||
}, /*#__PURE__*/React.createElement(Form, {
|
||||
isHorizontal: true
|
||||
}, this.props.permissions.map((p, row) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FormGroup, {
|
||||
fieldId: `username-${row}`,
|
||||
label: Msg.localize('User')
|
||||
}, /*#__PURE__*/React.createElement(TextInput, {
|
||||
id: `username-${row}`,
|
||||
type: "text",
|
||||
value: p.username,
|
||||
isDisabled: true
|
||||
})), /*#__PURE__*/React.createElement(FormGroup, {
|
||||
fieldId: `permissions-${row}`,
|
||||
label: Msg.localize('permissions'),
|
||||
isRequired: true
|
||||
}, /*#__PURE__*/React.createElement(InputGroup, null, /*#__PURE__*/React.createElement(PermissionSelect, {
|
||||
scopes: this.props.resource.scopes,
|
||||
selected: p.scopes.map(s => new Scope(s)),
|
||||
direction: row === this.props.permissions.length - 1 ? "up" : "down",
|
||||
onSelect: selection => {
|
||||
p.scopes = selection.map(s => s.name);
|
||||
this.updateChanged(row);
|
||||
}
|
||||
}), /*#__PURE__*/React.createElement(Button, {
|
||||
id: `save-${row}`,
|
||||
isDisabled: !this.state.changed[row],
|
||||
onClick: () => this.savePermission(p)
|
||||
}, /*#__PURE__*/React.createElement(OkIcon, null)))), /*#__PURE__*/React.createElement("hr", null))))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_defineProperty(EditTheResource, "defaultProps", {
|
||||
permissions: []
|
||||
});
|
||||
|
||||
_defineProperty(EditTheResource, "contextType", AccountServiceContext);
|
||||
//# sourceMappingURL=EditTheResource.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+284
@@ -0,0 +1,284 @@
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import parse from "../../util/ParseLink.js";
|
||||
import { Button, Level, LevelItem, PageSection, PageSectionVariants, Stack, StackItem, Tab, Tabs, TextInput } from "../../../../common/keycloak/web_modules/@patternfly/react-core.js";
|
||||
import { AccountServiceContext } from "../../account-service/AccountServiceContext.js";
|
||||
import { Scope } from "./resource-model.js";
|
||||
import { ResourcesTable } from "./ResourcesTable.js";
|
||||
import { ContentPage } from "../ContentPage.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
import { SharedResourcesTable } from "./SharedResourcesTable.js";
|
||||
const MY_RESOURCES_TAB = 0;
|
||||
const SHARED_WITH_ME_TAB = 1;
|
||||
export class MyResourcesPage extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
_defineProperty(this, "context", void 0);
|
||||
|
||||
_defineProperty(this, "first", 0);
|
||||
|
||||
_defineProperty(this, "max", 5);
|
||||
|
||||
_defineProperty(this, "makeScopeObj", scope => {
|
||||
return new Scope(scope.name, scope.displayName);
|
||||
});
|
||||
|
||||
_defineProperty(this, "fetchPermissionRequests", () => {
|
||||
this.state.myResources.data.forEach(resource => {
|
||||
this.fetchShareRequests(resource);
|
||||
});
|
||||
});
|
||||
|
||||
_defineProperty(this, "fetchPending", async () => {
|
||||
const response = await this.context.doGet(`/resources/pending-requests`);
|
||||
const resources = response.data || [];
|
||||
resources.forEach(pendingRequest => {
|
||||
this.state.sharedWithMe.data.forEach(resource => {
|
||||
if (resource._id === pendingRequest._id) {
|
||||
resource.shareRequests = [{
|
||||
username: 'me',
|
||||
scopes: pendingRequest.scopes
|
||||
}];
|
||||
this.forceUpdate();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleFilterRequest", value => {
|
||||
this.setState({
|
||||
nameFilter: value
|
||||
});
|
||||
this.fetchFilteredResources({
|
||||
name: value
|
||||
});
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleFirstPageClick", () => {
|
||||
this.fetchInitialResources();
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleNextClick", () => {
|
||||
if (this.isSharedWithMeTab()) {
|
||||
this.fetchResources(this.state.sharedWithMe.nextUrl);
|
||||
} else {
|
||||
this.fetchResources(this.state.myResources.nextUrl);
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "handlePreviousClick", () => {
|
||||
if (this.isSharedWithMeTab()) {
|
||||
this.fetchResources(this.state.sharedWithMe.prevUrl);
|
||||
} else {
|
||||
this.fetchResources(this.state.myResources.prevUrl);
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleTabClick", (event, tabIndex) => {
|
||||
if (this.state.activeTabKey === tabIndex) return;
|
||||
this.setState({
|
||||
nameFilter: '',
|
||||
activeTabKey: tabIndex
|
||||
}, () => {
|
||||
this.fetchInitialResources();
|
||||
});
|
||||
});
|
||||
|
||||
this.context = context;
|
||||
this.state = {
|
||||
activeTabKey: MY_RESOURCES_TAB,
|
||||
nameFilter: '',
|
||||
isModalOpen: false,
|
||||
myResources: {
|
||||
nextUrl: '',
|
||||
prevUrl: '',
|
||||
data: []
|
||||
},
|
||||
sharedWithMe: {
|
||||
nextUrl: '',
|
||||
prevUrl: '',
|
||||
data: []
|
||||
}
|
||||
};
|
||||
this.fetchInitialResources();
|
||||
}
|
||||
|
||||
isSharedWithMeTab() {
|
||||
return this.state.activeTabKey === SHARED_WITH_ME_TAB;
|
||||
}
|
||||
|
||||
hasNext() {
|
||||
if (this.isSharedWithMeTab()) {
|
||||
return this.state.sharedWithMe.nextUrl !== null && this.state.sharedWithMe.nextUrl !== '';
|
||||
} else {
|
||||
return this.state.myResources.nextUrl !== null && this.state.myResources.nextUrl !== '';
|
||||
}
|
||||
}
|
||||
|
||||
hasPrevious() {
|
||||
if (this.isSharedWithMeTab()) {
|
||||
return this.state.sharedWithMe.prevUrl !== null && this.state.sharedWithMe.prevUrl !== '';
|
||||
} else {
|
||||
return this.state.myResources.prevUrl !== null && this.state.myResources.prevUrl !== '';
|
||||
}
|
||||
}
|
||||
|
||||
fetchInitialResources() {
|
||||
if (this.isSharedWithMeTab()) {
|
||||
this.fetchResources("/resources/shared-with-me");
|
||||
} else {
|
||||
this.fetchResources("/resources", {
|
||||
first: this.first,
|
||||
max: this.max
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fetchFilteredResources(params) {
|
||||
if (this.isSharedWithMeTab()) {
|
||||
this.fetchResources("/resources/shared-with-me", params);
|
||||
} else {
|
||||
this.fetchResources("/resources", { ...params,
|
||||
first: this.first,
|
||||
max: this.max
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fetchResources(url, extraParams) {
|
||||
this.context.doGet(url, {
|
||||
params: extraParams
|
||||
}).then(response => {
|
||||
const resources = response.data || [];
|
||||
resources.forEach(resource => resource.shareRequests = []); // serialize the Scope objects from JSON so that toString() will work.
|
||||
|
||||
resources.forEach(resource => resource.scopes = resource.scopes.map(this.makeScopeObj));
|
||||
|
||||
if (this.isSharedWithMeTab()) {
|
||||
this.setState({
|
||||
sharedWithMe: this.parseResourceResponse(response)
|
||||
}, this.fetchPending);
|
||||
} else {
|
||||
this.setState({
|
||||
myResources: this.parseResourceResponse(response)
|
||||
}, this.fetchPermissionRequests);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fetchShareRequests(resource) {
|
||||
this.context.doGet('/resources/' + resource._id + '/permissions/requests').then(response => {
|
||||
resource.shareRequests = response.data || [];
|
||||
|
||||
if (resource.shareRequests.length > 0) {
|
||||
this.forceUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
parseResourceResponse(response) {
|
||||
const links = response.headers.get('link') || undefined;
|
||||
const parsed = parse(links);
|
||||
let next = '';
|
||||
let prev = '';
|
||||
|
||||
if (parsed !== null) {
|
||||
if (parsed.next) next = parsed.next;
|
||||
if (parsed.prev) prev = parsed.prev;
|
||||
}
|
||||
|
||||
const resources = response.data || [];
|
||||
return {
|
||||
nextUrl: next,
|
||||
prevUrl: prev,
|
||||
data: resources
|
||||
};
|
||||
}
|
||||
|
||||
makeTab(eventKey, title, resources, sharedResourcesTab) {
|
||||
return /*#__PURE__*/React.createElement(Tab, {
|
||||
id: title,
|
||||
eventKey: eventKey,
|
||||
title: Msg.localize(title)
|
||||
}, /*#__PURE__*/React.createElement(Stack, {
|
||||
hasGutter: true
|
||||
}, /*#__PURE__*/React.createElement(StackItem, {
|
||||
isFilled: true
|
||||
}, /*#__PURE__*/React.createElement("span", null)), /*#__PURE__*/React.createElement(StackItem, {
|
||||
isFilled: true
|
||||
}, /*#__PURE__*/React.createElement(Level, {
|
||||
hasGutter: true
|
||||
}, /*#__PURE__*/React.createElement(LevelItem, null, /*#__PURE__*/React.createElement(TextInput, {
|
||||
value: this.state.nameFilter,
|
||||
onChange: this.handleFilterRequest,
|
||||
id: 'filter-' + title,
|
||||
type: "text",
|
||||
placeholder: Msg.localize('filterByName'),
|
||||
iconVariant: "search"
|
||||
})))), /*#__PURE__*/React.createElement(StackItem, {
|
||||
isFilled: true
|
||||
}, !sharedResourcesTab && /*#__PURE__*/React.createElement(ResourcesTable, {
|
||||
resources: resources
|
||||
}), sharedResourcesTab && /*#__PURE__*/React.createElement(SharedResourcesTable, {
|
||||
resources: resources
|
||||
}))));
|
||||
}
|
||||
|
||||
render() {
|
||||
return /*#__PURE__*/React.createElement(ContentPage, {
|
||||
title: "resources",
|
||||
onRefresh: this.fetchInitialResources.bind(this)
|
||||
}, /*#__PURE__*/React.createElement(PageSection, {
|
||||
variant: PageSectionVariants.light
|
||||
}, /*#__PURE__*/React.createElement(Tabs, {
|
||||
activeKey: this.state.activeTabKey,
|
||||
onSelect: this.handleTabClick
|
||||
}, this.makeTab(0, 'myResources', this.state.myResources, false), this.makeTab(1, 'sharedwithMe', this.state.sharedWithMe, true)), /*#__PURE__*/React.createElement(Level, {
|
||||
hasGutter: true
|
||||
}, /*#__PURE__*/React.createElement(LevelItem, null, this.hasPrevious() && /*#__PURE__*/React.createElement(Button, {
|
||||
onClick: this.handlePreviousClick
|
||||
}, "<", /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "previousPage"
|
||||
}))), /*#__PURE__*/React.createElement(LevelItem, null, this.hasPrevious() && /*#__PURE__*/React.createElement(Button, {
|
||||
onClick: this.handleFirstPageClick
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "firstPage"
|
||||
}))), /*#__PURE__*/React.createElement(LevelItem, null, this.hasNext() && /*#__PURE__*/React.createElement(Button, {
|
||||
onClick: this.handleNextClick
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "nextPage"
|
||||
}), ">")))));
|
||||
}
|
||||
|
||||
clearNextPrev() {
|
||||
const newMyResources = this.state.myResources;
|
||||
newMyResources.nextUrl = '';
|
||||
newMyResources.prevUrl = '';
|
||||
this.setState({
|
||||
myResources: newMyResources
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_defineProperty(MyResourcesPage, "contextType", AccountServiceContext);
|
||||
|
||||
;
|
||||
//# sourceMappingURL=MyResourcesPage.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+151
@@ -0,0 +1,151 @@
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
/*
|
||||
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import { Button, Modal, Text, Badge, DataListItem, DataList, TextVariants, DataListItemRow, DataListItemCells, DataListCell, Chip, Split, SplitItem, ModalVariant } from "../../../../common/keycloak/web_modules/@patternfly/react-core.js";
|
||||
import { UserCheckIcon } from "../../../../common/keycloak/web_modules/@patternfly/react-icons.js";
|
||||
import { AccountServiceContext } from "../../account-service/AccountServiceContext.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
import { ContentAlert } from "../ContentAlert.js";
|
||||
export class PermissionRequest extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
_defineProperty(this, "context", void 0);
|
||||
|
||||
_defineProperty(this, "handleApprove", async (shareRequest, index) => {
|
||||
this.handle(shareRequest.username, shareRequest.scopes, true);
|
||||
this.props.resource.shareRequests.splice(index, 1);
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleDeny", async (shareRequest, index) => {
|
||||
this.handle(shareRequest.username, shareRequest.scopes);
|
||||
this.props.resource.shareRequests.splice(index, 1);
|
||||
});
|
||||
|
||||
_defineProperty(this, "handle", async (username, scopes, approve = false) => {
|
||||
const id = this.props.resource._id;
|
||||
this.handleToggleDialog();
|
||||
const permissionsRequest = await this.context.doGet(`/resources/${id}/permissions`);
|
||||
const permissions = permissionsRequest.data || [];
|
||||
const foundPermission = permissions.find(p => p.username === username);
|
||||
const userScopes = foundPermission ? foundPermission.scopes : [];
|
||||
|
||||
if (approve) {
|
||||
userScopes.push(...scopes);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.context.doPut(`/resources/${id}/permissions`, [{
|
||||
username: username,
|
||||
scopes: userScopes
|
||||
}]);
|
||||
ContentAlert.success(Msg.localize('shareSuccess'));
|
||||
this.props.onClose();
|
||||
} catch (e) {
|
||||
console.error('Could not update permissions', e.error);
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleToggleDialog", () => {
|
||||
this.setState({
|
||||
isOpen: !this.state.isOpen
|
||||
});
|
||||
});
|
||||
|
||||
this.context = context;
|
||||
this.state = {
|
||||
isOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const id = `shareRequest-${this.props.resource.name.replace(/\s/, '-')}`;
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||||
id: id,
|
||||
variant: "link",
|
||||
onClick: this.handleToggleDialog
|
||||
}, /*#__PURE__*/React.createElement(UserCheckIcon, {
|
||||
size: "lg"
|
||||
}), /*#__PURE__*/React.createElement(Badge, null, this.props.resource.shareRequests.length)), /*#__PURE__*/React.createElement(Modal, {
|
||||
id: `modal-${id}`,
|
||||
title: Msg.localize('permissionRequests') + ' - ' + this.props.resource.name,
|
||||
variant: ModalVariant.large,
|
||||
isOpen: this.state.isOpen,
|
||||
onClose: this.handleToggleDialog,
|
||||
actions: [/*#__PURE__*/React.createElement(Button, {
|
||||
id: `close-${id}`,
|
||||
key: "close",
|
||||
variant: "link",
|
||||
onClick: this.handleToggleDialog
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "close"
|
||||
}))]
|
||||
}, /*#__PURE__*/React.createElement(DataList, {
|
||||
"aria-label": Msg.localize('permissionRequests')
|
||||
}, /*#__PURE__*/React.createElement(DataListItemRow, null, /*#__PURE__*/React.createElement(DataListItemCells, {
|
||||
dataListCells: [/*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "permissions-name-header",
|
||||
width: 5
|
||||
}, /*#__PURE__*/React.createElement("strong", null, "Requestor")), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "permissions-requested-header",
|
||||
width: 5
|
||||
}, /*#__PURE__*/React.createElement("strong", null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "permissionRequests"
|
||||
}))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "permission-request-header",
|
||||
width: 5
|
||||
})]
|
||||
})), this.props.resource.shareRequests.map((shareRequest, i) => /*#__PURE__*/React.createElement(DataListItem, {
|
||||
key: i,
|
||||
"aria-labelledby": "requestor"
|
||||
}, /*#__PURE__*/React.createElement(DataListItemRow, null, /*#__PURE__*/React.createElement(DataListItemCells, {
|
||||
dataListCells: [/*#__PURE__*/React.createElement(DataListCell, {
|
||||
id: `requestor${i}`,
|
||||
key: `requestor${i}`
|
||||
}, /*#__PURE__*/React.createElement("span", null, shareRequest.firstName, " ", shareRequest.lastName, " ", shareRequest.lastName ? '' : shareRequest.username), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(Text, {
|
||||
component: TextVariants.small
|
||||
}, shareRequest.email)), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
id: `permissions${i}`,
|
||||
key: `permissions${i}`
|
||||
}, shareRequest.scopes.map((scope, j) => /*#__PURE__*/React.createElement(Chip, {
|
||||
key: j,
|
||||
isReadOnly: true
|
||||
}, scope))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: `actions${i}`
|
||||
}, /*#__PURE__*/React.createElement(Split, {
|
||||
hasGutter: true
|
||||
}, /*#__PURE__*/React.createElement(SplitItem, null, /*#__PURE__*/React.createElement(Button, {
|
||||
id: `accept-${i}-${id}`,
|
||||
onClick: () => this.handleApprove(shareRequest, i)
|
||||
}, "Accept")), /*#__PURE__*/React.createElement(SplitItem, null, /*#__PURE__*/React.createElement(Button, {
|
||||
id: `deny-${i}-${id}`,
|
||||
variant: "danger",
|
||||
onClick: () => this.handleDeny(shareRequest, i)
|
||||
}, "Deny"))))]
|
||||
})))))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_defineProperty(PermissionRequest, "defaultProps", {
|
||||
permissions: [],
|
||||
row: 0
|
||||
});
|
||||
|
||||
_defineProperty(PermissionRequest, "contextType", AccountServiceContext);
|
||||
//# sourceMappingURL=PermissionRequest.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+103
@@ -0,0 +1,103 @@
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import { Select, SelectOption, SelectVariant } from "../../../../common/keycloak/web_modules/@patternfly/react-core.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
|
||||
class ScopeValue {
|
||||
constructor(value) {
|
||||
_defineProperty(this, "value", void 0);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value.displayName ? this.value.displayName : this.value.name;
|
||||
}
|
||||
|
||||
compareTo(selectOption) {
|
||||
return selectOption.name === this.value.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class PermissionSelect extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
_defineProperty(this, "onSelect", (_event, selection) => {
|
||||
const {
|
||||
selected
|
||||
} = this.state;
|
||||
const {
|
||||
onSelect
|
||||
} = this.props;
|
||||
|
||||
if (selected.includes(selection)) {
|
||||
this.setState(prevState => ({
|
||||
selected: prevState.selected.filter(item => item !== selection)
|
||||
}), () => onSelect(this.state.selected.map(sv => sv.value)));
|
||||
} else {
|
||||
this.setState(prevState => ({
|
||||
selected: [...prevState.selected, selection]
|
||||
}), () => onSelect(this.state.selected.map(sv => sv.value)));
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "onToggle", isExpanded => {
|
||||
this.setState({
|
||||
isExpanded
|
||||
});
|
||||
});
|
||||
|
||||
_defineProperty(this, "clearSelection", () => {
|
||||
this.setState({
|
||||
selected: [],
|
||||
isExpanded: false
|
||||
});
|
||||
this.props.onSelect([]);
|
||||
});
|
||||
|
||||
let values = [];
|
||||
|
||||
if (this.props.selected) {
|
||||
values = this.props.selected.map(s => new ScopeValue(s));
|
||||
}
|
||||
|
||||
this.state = {
|
||||
isExpanded: false,
|
||||
selected: values,
|
||||
scopes: this.props.scopes.map((option, index) => /*#__PURE__*/React.createElement(SelectOption, {
|
||||
key: index,
|
||||
value: values.find(s => s.compareTo(option)) || new ScopeValue(option)
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isExpanded,
|
||||
selected
|
||||
} = this.state;
|
||||
const titleId = 'permission-id';
|
||||
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("span", {
|
||||
id: titleId,
|
||||
hidden: true
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "selectPermissions"
|
||||
})), /*#__PURE__*/React.createElement(Select, {
|
||||
direction: this.props.direction || 'down',
|
||||
variant: SelectVariant.typeaheadMulti,
|
||||
typeAheadAriaLabel: Msg.localize("selectPermissions"),
|
||||
onToggle: this.onToggle,
|
||||
onSelect: this.onSelect,
|
||||
onClear: this.clearSelection,
|
||||
selections: selected,
|
||||
isOpen: isExpanded,
|
||||
"aria-labelledby": titleId,
|
||||
placeholderText: Msg.localize("selectPermissions")
|
||||
}, this.state.scopes));
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=PermissionSelect.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+313
@@ -0,0 +1,313 @@
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import { DataList, DataListItem, DataListItemRow, DataListCell, DataListToggle, DataListContent, DataListItemCells, Level, LevelItem, Button, DataListAction, Dropdown, DropdownPosition, DropdownItem, KebabToggle } from "../../../../common/keycloak/web_modules/@patternfly/react-core.js";
|
||||
import { Remove2Icon, RepositoryIcon, ShareAltIcon, EditAltIcon } from "../../../../common/keycloak/web_modules/@patternfly/react-icons.js";
|
||||
import { AccountServiceContext } from "../../account-service/AccountServiceContext.js";
|
||||
import { PermissionRequest } from "./PermissionRequest.js";
|
||||
import { ShareTheResource } from "./ShareTheResource.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
import { AbstractResourcesTable } from "./AbstractResourceTable.js";
|
||||
import { EditTheResource } from "./EditTheResource.js";
|
||||
import { ContentAlert } from "../ContentAlert.js";
|
||||
import EmptyMessageState from "../../widgets/EmptyMessageState.js";
|
||||
import { ContinueCancelModal } from "../../widgets/ContinueCancelModal.js";
|
||||
export class ResourcesTable extends AbstractResourcesTable {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
_defineProperty(this, "context", void 0);
|
||||
|
||||
_defineProperty(this, "onToggle", row => {
|
||||
const newIsRowOpen = this.state.isRowOpen;
|
||||
newIsRowOpen[row] = !newIsRowOpen[row];
|
||||
if (newIsRowOpen[row]) this.fetchPermissions(this.props.resources.data[row], row);
|
||||
this.setState({
|
||||
isRowOpen: newIsRowOpen
|
||||
});
|
||||
});
|
||||
|
||||
_defineProperty(this, "onContextToggle", (row, isOpen) => {
|
||||
if (this.state.isModalActive) return;
|
||||
const data = this.props.resources.data;
|
||||
const contextOpen = this.state.contextOpen;
|
||||
contextOpen[row] = isOpen;
|
||||
|
||||
if (isOpen) {
|
||||
const index = row > data.length ? row - data.length - 1 : row;
|
||||
this.fetchPermissions(data[index], index);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
contextOpen
|
||||
});
|
||||
});
|
||||
|
||||
this.context = context;
|
||||
this.state = {
|
||||
isRowOpen: [],
|
||||
contextOpen: [],
|
||||
isModalActive: false,
|
||||
permissions: new Map()
|
||||
};
|
||||
}
|
||||
|
||||
fetchPermissions(resource, row) {
|
||||
this.context.doGet(`/resources/${resource._id}/permissions`).then(response => {
|
||||
const newPermissions = new Map(this.state.permissions);
|
||||
newPermissions.set(row, response.data || []);
|
||||
this.setState({
|
||||
permissions: newPermissions
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
removeShare(resource, row) {
|
||||
const permissions = this.state.permissions.get(row).map(a => ({
|
||||
username: a.username,
|
||||
scopes: []
|
||||
}));
|
||||
return this.context.doPut(`/resources/${resource._id}/permissions`, permissions).then(() => {
|
||||
ContentAlert.success(Msg.localize('unShareSuccess'));
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.resources.data.length === 0) {
|
||||
return /*#__PURE__*/React.createElement(EmptyMessageState, {
|
||||
icon: RepositoryIcon,
|
||||
messageKey: "notHaveAnyResource"
|
||||
});
|
||||
}
|
||||
|
||||
return /*#__PURE__*/React.createElement(DataList, {
|
||||
"aria-label": Msg.localize('resources'),
|
||||
id: "resourcesList"
|
||||
}, /*#__PURE__*/React.createElement(DataListItem, {
|
||||
key: "resource-header",
|
||||
"aria-labelledby": "resource-header"
|
||||
}, /*#__PURE__*/React.createElement(DataListItemRow, null, "// invisible toggle allows headings to line up properly", /*#__PURE__*/React.createElement("span", {
|
||||
style: {
|
||||
visibility: 'hidden'
|
||||
}
|
||||
}, /*#__PURE__*/React.createElement(DataListToggle, {
|
||||
isExpanded: false,
|
||||
id: "resource-header-invisible-toggle",
|
||||
"aria-controls": "ex-expand1"
|
||||
})), /*#__PURE__*/React.createElement(DataListItemCells, {
|
||||
dataListCells: [/*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "resource-name-header",
|
||||
width: 5
|
||||
}, /*#__PURE__*/React.createElement("strong", null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "resourceName"
|
||||
}))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "application-name-header",
|
||||
width: 5
|
||||
}, /*#__PURE__*/React.createElement("strong", null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "application"
|
||||
}))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "permission-request-header",
|
||||
width: 5
|
||||
}, /*#__PURE__*/React.createElement("strong", null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "permissionRequests"
|
||||
})))]
|
||||
}))), this.props.resources.data.map((resource, row) => /*#__PURE__*/React.createElement(DataListItem, {
|
||||
key: 'resource-' + row,
|
||||
"aria-labelledby": resource.name,
|
||||
isExpanded: this.state.isRowOpen[row]
|
||||
}, /*#__PURE__*/React.createElement(DataListItemRow, null, /*#__PURE__*/React.createElement(DataListToggle, {
|
||||
onClick: () => this.onToggle(row),
|
||||
isExpanded: this.state.isRowOpen[row],
|
||||
id: 'resourceToggle-' + row,
|
||||
"aria-controls": "ex-expand1"
|
||||
}), /*#__PURE__*/React.createElement(DataListItemCells, {
|
||||
dataListCells: [/*#__PURE__*/React.createElement(DataListCell, {
|
||||
id: 'resourceName-' + row,
|
||||
key: 'resourceName-' + row,
|
||||
width: 5
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: resource.name
|
||||
})), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
id: 'resourceClient-' + row,
|
||||
key: 'resourceClient-' + row,
|
||||
width: 5
|
||||
}, /*#__PURE__*/React.createElement("a", {
|
||||
href: resource.client.baseUrl
|
||||
}, this.getClientName(resource.client))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
id: 'resourceRequests-' + row,
|
||||
key: 'permissionRequests-' + row,
|
||||
width: 5
|
||||
}, resource.shareRequests.length > 0 && /*#__PURE__*/React.createElement(PermissionRequest, {
|
||||
resource: resource,
|
||||
onClose: () => this.fetchPermissions(resource, row)
|
||||
}))]
|
||||
}), /*#__PURE__*/React.createElement(DataListAction, {
|
||||
visibility: {
|
||||
lg: 'hidden'
|
||||
},
|
||||
"aria-labelledby": "check-action-item3 check-action-action3",
|
||||
id: "check-action-action3",
|
||||
"aria-label": "Actions"
|
||||
}, /*#__PURE__*/React.createElement(Dropdown, {
|
||||
isPlain: true,
|
||||
position: DropdownPosition.right,
|
||||
onSelect: () => this.setState({
|
||||
isModalActive: true
|
||||
}),
|
||||
toggle: /*#__PURE__*/React.createElement(KebabToggle, {
|
||||
onToggle: isOpen => this.onContextToggle(row + this.props.resources.data.length + 1, isOpen)
|
||||
}),
|
||||
isOpen: this.state.contextOpen[row + this.props.resources.data.length + 1],
|
||||
dropdownItems: [/*#__PURE__*/React.createElement(ShareTheResource, {
|
||||
resource: resource,
|
||||
permissions: this.state.permissions.get(row),
|
||||
sharedWithUsersMsg: this.sharedWithUsersMessage(row),
|
||||
onClose: () => {
|
||||
this.setState({
|
||||
isModalActive: false
|
||||
}, () => {
|
||||
this.onContextToggle(row + this.props.resources.data.length + 1, false);
|
||||
this.fetchPermissions(resource, row + this.props.resources.data.length + 1);
|
||||
});
|
||||
}
|
||||
}, toggle => /*#__PURE__*/React.createElement(DropdownItem, {
|
||||
id: 'mob-share-' + row,
|
||||
key: "mob-share",
|
||||
onClick: toggle
|
||||
}, /*#__PURE__*/React.createElement(ShareAltIcon, null), " ", /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "share"
|
||||
}))), /*#__PURE__*/React.createElement(EditTheResource, {
|
||||
resource: resource,
|
||||
permissions: this.state.permissions.get(row),
|
||||
onClose: () => {
|
||||
this.setState({
|
||||
isModalActive: false
|
||||
}, () => {
|
||||
this.onContextToggle(row + this.props.resources.data.length + 1, false);
|
||||
this.fetchPermissions(resource, row + this.props.resources.data.length + 1);
|
||||
});
|
||||
}
|
||||
}, toggle => /*#__PURE__*/React.createElement(DropdownItem, {
|
||||
id: 'mob-edit-' + row,
|
||||
key: "mob-edit",
|
||||
isDisabled: this.numOthers(row) < 0,
|
||||
onClick: toggle
|
||||
}, /*#__PURE__*/React.createElement(EditAltIcon, null), " ", /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "edit"
|
||||
}))), /*#__PURE__*/React.createElement(ContinueCancelModal, {
|
||||
render: toggle => /*#__PURE__*/React.createElement(DropdownItem, {
|
||||
id: 'mob-remove-' + row,
|
||||
key: "mob-remove",
|
||||
isDisabled: this.numOthers(row) < 0,
|
||||
onClick: toggle
|
||||
}, /*#__PURE__*/React.createElement(Remove2Icon, null), " ", /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "unShare"
|
||||
})),
|
||||
modalTitle: "unShare",
|
||||
modalMessage: "unShareAllConfirm",
|
||||
onClose: () => this.setState({
|
||||
isModalActive: false
|
||||
}, () => {
|
||||
this.onContextToggle(row + this.props.resources.data.length + 1, false);
|
||||
}),
|
||||
onContinue: () => this.removeShare(resource, row).then(() => this.fetchPermissions(resource, row + this.props.resources.data.length + 1))
|
||||
})]
|
||||
})), /*#__PURE__*/React.createElement(DataListAction, {
|
||||
id: `actions-${row}`,
|
||||
visibility: {
|
||||
default: 'hidden',
|
||||
lg: 'visible'
|
||||
},
|
||||
"aria-labelledby": "Row actions",
|
||||
"aria-label": "Actions"
|
||||
}, /*#__PURE__*/React.createElement(ShareTheResource, {
|
||||
resource: resource,
|
||||
permissions: this.state.permissions.get(row),
|
||||
sharedWithUsersMsg: this.sharedWithUsersMessage(row),
|
||||
onClose: () => this.fetchPermissions(resource, row)
|
||||
}, toggle => /*#__PURE__*/React.createElement(Button, {
|
||||
id: `share-${row}`,
|
||||
variant: "link",
|
||||
onClick: toggle
|
||||
}, /*#__PURE__*/React.createElement(ShareAltIcon, null), " ", /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "share"
|
||||
}))), /*#__PURE__*/React.createElement(Dropdown, {
|
||||
id: `action-menu-${row}`,
|
||||
isPlain: true,
|
||||
position: DropdownPosition.right,
|
||||
toggle: /*#__PURE__*/React.createElement(KebabToggle, {
|
||||
onToggle: isOpen => this.onContextToggle(row, isOpen)
|
||||
}),
|
||||
onSelect: () => this.setState({
|
||||
isModalActive: true
|
||||
}),
|
||||
isOpen: this.state.contextOpen[row],
|
||||
dropdownItems: [/*#__PURE__*/React.createElement(EditTheResource, {
|
||||
resource: resource,
|
||||
permissions: this.state.permissions.get(row),
|
||||
onClose: () => {
|
||||
this.setState({
|
||||
isModalActive: false
|
||||
}, () => {
|
||||
this.onContextToggle(row, false);
|
||||
this.fetchPermissions(resource, row);
|
||||
});
|
||||
}
|
||||
}, toggle => /*#__PURE__*/React.createElement(DropdownItem, {
|
||||
id: 'edit-' + row,
|
||||
key: "edit",
|
||||
component: "button",
|
||||
isDisabled: this.numOthers(row) < 0,
|
||||
onClick: toggle
|
||||
}, /*#__PURE__*/React.createElement(EditAltIcon, null), " ", /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "edit"
|
||||
}))), /*#__PURE__*/React.createElement(ContinueCancelModal, {
|
||||
render: toggle => /*#__PURE__*/React.createElement(DropdownItem, {
|
||||
id: 'remove-' + row,
|
||||
key: "remove",
|
||||
component: "button",
|
||||
isDisabled: this.numOthers(row) < 0,
|
||||
onClick: toggle
|
||||
}, /*#__PURE__*/React.createElement(Remove2Icon, null), " ", /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "unShare"
|
||||
})),
|
||||
modalTitle: "unShare",
|
||||
modalMessage: "unShareAllConfirm",
|
||||
onClose: () => this.setState({
|
||||
isModalActive: false
|
||||
}, () => {
|
||||
this.onContextToggle(row, false);
|
||||
}),
|
||||
onContinue: () => this.removeShare(resource, row).then(() => this.fetchPermissions(resource, row))
|
||||
})]
|
||||
}))), /*#__PURE__*/React.createElement(DataListContent, {
|
||||
hasNoPadding: false,
|
||||
"aria-label": "Session Details",
|
||||
id: 'ex-expand' + row,
|
||||
isHidden: !this.state.isRowOpen[row]
|
||||
}, /*#__PURE__*/React.createElement(Level, {
|
||||
hasGutter: true
|
||||
}, /*#__PURE__*/React.createElement(LevelItem, null, /*#__PURE__*/React.createElement("span", null)), /*#__PURE__*/React.createElement(LevelItem, {
|
||||
id: 'shared-with-user-message-' + row
|
||||
}, this.sharedWithUsersMessage(row)), /*#__PURE__*/React.createElement(LevelItem, null, /*#__PURE__*/React.createElement("span", null)))))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_defineProperty(ResourcesTable, "contextType", AccountServiceContext);
|
||||
//# sourceMappingURL=ResourcesTable.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+222
@@ -0,0 +1,222 @@
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
/*
|
||||
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import { Button, Chip, ChipGroup, Form, FormGroup, Gallery, GalleryItem, Modal, Stack, StackItem, TextInput, ModalVariant } from "../../../../common/keycloak/web_modules/@patternfly/react-core.js";
|
||||
import { AccountServiceContext } from "../../account-service/AccountServiceContext.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
import { ContentAlert } from "../ContentAlert.js";
|
||||
import { PermissionSelect } from "./PermissionSelect.js";
|
||||
|
||||
/**
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2019 Red Hat Inc.
|
||||
*/
|
||||
export class ShareTheResource extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
_defineProperty(this, "context", void 0);
|
||||
|
||||
_defineProperty(this, "handleAddPermission", () => {
|
||||
const rscId = this.props.resource._id;
|
||||
const newPermissions = [];
|
||||
|
||||
for (const permission of this.state.permissionsSelected) {
|
||||
newPermissions.push(permission.name);
|
||||
}
|
||||
|
||||
const permissions = [];
|
||||
|
||||
for (const username of this.state.usernames) {
|
||||
permissions.push({
|
||||
username: username,
|
||||
scopes: newPermissions
|
||||
});
|
||||
}
|
||||
|
||||
this.handleToggleDialog();
|
||||
this.context.doPut(`/resources/${rscId}/permissions`, permissions).then(() => {
|
||||
ContentAlert.success('shareSuccess');
|
||||
this.props.onClose();
|
||||
});
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleToggleDialog", () => {
|
||||
if (this.state.isOpen) {
|
||||
this.setState({
|
||||
isOpen: false
|
||||
});
|
||||
this.props.onClose();
|
||||
} else {
|
||||
this.clearState();
|
||||
this.setState({
|
||||
isOpen: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleUsernameChange", username => {
|
||||
this.setState({
|
||||
usernameInput: username
|
||||
});
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleAddUsername", async () => {
|
||||
if (this.state.usernameInput !== '' && !this.state.usernames.includes(this.state.usernameInput)) {
|
||||
const response = await this.context.doGet(`/resources/${this.props.resource._id}/user`, {
|
||||
params: {
|
||||
value: this.state.usernameInput
|
||||
}
|
||||
});
|
||||
|
||||
if (response.data && response.data.username) {
|
||||
this.setState({
|
||||
usernameInput: '',
|
||||
usernames: [...this.state.usernames, this.state.usernameInput]
|
||||
});
|
||||
} else {
|
||||
ContentAlert.info('userNotFound', [this.state.usernameInput]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleEnterKeyInAddField", event => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
this.handleAddUsername();
|
||||
}
|
||||
});
|
||||
|
||||
_defineProperty(this, "handleDeleteUsername", username => {
|
||||
const newUsernames = this.state.usernames.filter(user => user !== username);
|
||||
this.setState({
|
||||
usernames: newUsernames
|
||||
});
|
||||
});
|
||||
|
||||
this.context = context;
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
permissionsSelected: [],
|
||||
permissionsUnSelected: this.props.resource.scopes,
|
||||
usernames: [],
|
||||
usernameInput: ''
|
||||
};
|
||||
}
|
||||
|
||||
clearState() {
|
||||
this.setState({
|
||||
permissionsSelected: [],
|
||||
permissionsUnSelected: this.props.resource.scopes,
|
||||
usernames: [],
|
||||
usernameInput: ''
|
||||
});
|
||||
}
|
||||
|
||||
isAddDisabled() {
|
||||
return this.state.usernameInput === '' || this.isAlreadyShared();
|
||||
}
|
||||
|
||||
isAlreadyShared() {
|
||||
for (let permission of this.props.permissions) {
|
||||
if (permission.username === this.state.usernameInput) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
isFormInvalid() {
|
||||
return this.state.usernames.length === 0 || this.state.permissionsSelected.length === 0;
|
||||
}
|
||||
|
||||
render() {
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, this.props.children(this.handleToggleDialog), /*#__PURE__*/React.createElement(Modal, {
|
||||
title: 'Share the resource - ' + this.props.resource.name,
|
||||
variant: ModalVariant.large,
|
||||
isOpen: this.state.isOpen,
|
||||
onClose: this.handleToggleDialog,
|
||||
actions: [/*#__PURE__*/React.createElement(Button, {
|
||||
key: "cancel",
|
||||
variant: "link",
|
||||
onClick: this.handleToggleDialog
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "cancel"
|
||||
})), /*#__PURE__*/React.createElement(Button, {
|
||||
key: "confirm",
|
||||
variant: "primary",
|
||||
id: "done",
|
||||
onClick: this.handleAddPermission,
|
||||
isDisabled: this.isFormInvalid()
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "done"
|
||||
}))]
|
||||
}, /*#__PURE__*/React.createElement(Stack, {
|
||||
hasGutter: true
|
||||
}, /*#__PURE__*/React.createElement(StackItem, {
|
||||
isFilled: true
|
||||
}, /*#__PURE__*/React.createElement(Form, null, /*#__PURE__*/React.createElement(FormGroup, {
|
||||
label: "Add users to share your resource with",
|
||||
type: "string",
|
||||
helperTextInvalid: Msg.localize('resourceAlreadyShared'),
|
||||
fieldId: "username",
|
||||
isRequired: true
|
||||
}, /*#__PURE__*/React.createElement(Gallery, {
|
||||
hasGutter: true
|
||||
}, /*#__PURE__*/React.createElement(GalleryItem, null, /*#__PURE__*/React.createElement(TextInput, {
|
||||
value: this.state.usernameInput,
|
||||
id: "username",
|
||||
"aria-describedby": "username-helper",
|
||||
placeholder: "Username or email",
|
||||
onChange: this.handleUsernameChange,
|
||||
onKeyPress: this.handleEnterKeyInAddField
|
||||
})), /*#__PURE__*/React.createElement(GalleryItem, null, /*#__PURE__*/React.createElement(Button, {
|
||||
key: "add-user",
|
||||
variant: "primary",
|
||||
id: "add",
|
||||
onClick: this.handleAddUsername,
|
||||
isDisabled: this.isAddDisabled()
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "add"
|
||||
})))), /*#__PURE__*/React.createElement(ChipGroup, {
|
||||
categoryName: Msg.localize('shareWith')
|
||||
}, this.state.usernames.map(currentChip => /*#__PURE__*/React.createElement(Chip, {
|
||||
key: currentChip,
|
||||
onClick: () => this.handleDeleteUsername(currentChip)
|
||||
}, currentChip)))), /*#__PURE__*/React.createElement(FormGroup, {
|
||||
label: "",
|
||||
fieldId: "permissions-selected"
|
||||
}, /*#__PURE__*/React.createElement(PermissionSelect, {
|
||||
scopes: this.state.permissionsUnSelected,
|
||||
onSelect: selection => this.setState({
|
||||
permissionsSelected: selection
|
||||
}),
|
||||
direction: "up"
|
||||
})))), /*#__PURE__*/React.createElement(StackItem, {
|
||||
isFilled: true
|
||||
}, /*#__PURE__*/React.createElement("br", null)), /*#__PURE__*/React.createElement(StackItem, {
|
||||
isFilled: true
|
||||
}, this.props.sharedWithUsersMsg))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_defineProperty(ShareTheResource, "defaultProps", {
|
||||
permissions: []
|
||||
});
|
||||
|
||||
_defineProperty(ShareTheResource, "contextType", AccountServiceContext);
|
||||
//# sourceMappingURL=ShareTheResource.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as React from "../../../../common/keycloak/web_modules/react.js";
|
||||
import { DataList, DataListItem, DataListItemRow, DataListCell, DataListItemCells, ChipGroup, Chip } from "../../../../common/keycloak/web_modules/@patternfly/react-core.js";
|
||||
import { RepositoryIcon } from "../../../../common/keycloak/web_modules/@patternfly/react-icons.js";
|
||||
import { Msg } from "../../widgets/Msg.js";
|
||||
import { AbstractResourcesTable } from "./AbstractResourceTable.js";
|
||||
import EmptyMessageState from "../../widgets/EmptyMessageState.js";
|
||||
export class SharedResourcesTable extends AbstractResourcesTable {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
permissions: new Map()
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.resources.data.length === 0) {
|
||||
return /*#__PURE__*/React.createElement(EmptyMessageState, {
|
||||
icon: RepositoryIcon,
|
||||
messageKey: "noResourcesSharedWithYou"
|
||||
});
|
||||
}
|
||||
|
||||
return /*#__PURE__*/React.createElement(DataList, {
|
||||
"aria-label": Msg.localize('resources'),
|
||||
id: "sharedResourcesList"
|
||||
}, /*#__PURE__*/React.createElement(DataListItem, {
|
||||
key: "resource-header",
|
||||
"aria-labelledby": "resource-header"
|
||||
}, /*#__PURE__*/React.createElement(DataListItemRow, null, /*#__PURE__*/React.createElement(DataListItemCells, {
|
||||
dataListCells: [/*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "resource-name-header",
|
||||
width: 2
|
||||
}, /*#__PURE__*/React.createElement("strong", null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "resourceName"
|
||||
}))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "application-name-header",
|
||||
width: 2
|
||||
}, /*#__PURE__*/React.createElement("strong", null, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: "application"
|
||||
}))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "permission-header",
|
||||
width: 2
|
||||
}), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: "requests-header",
|
||||
width: 2
|
||||
})]
|
||||
}))), this.props.resources.data.map((resource, row) => /*#__PURE__*/React.createElement(DataListItem, {
|
||||
key: 'resource-' + row,
|
||||
"aria-labelledby": resource.name
|
||||
}, /*#__PURE__*/React.createElement(DataListItemRow, null, /*#__PURE__*/React.createElement(DataListItemCells, {
|
||||
dataListCells: [/*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: 'resourceName-' + row,
|
||||
width: 2
|
||||
}, /*#__PURE__*/React.createElement(Msg, {
|
||||
msgKey: resource.name
|
||||
})), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: 'resourceClient-' + row,
|
||||
width: 2
|
||||
}, /*#__PURE__*/React.createElement("a", {
|
||||
href: resource.client.baseUrl
|
||||
}, this.getClientName(resource.client))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: 'permissions-' + row,
|
||||
width: 2
|
||||
}, resource.scopes.length > 0 && /*#__PURE__*/React.createElement(ChipGroup, {
|
||||
categoryName: Msg.localize('permissions')
|
||||
}, resource.scopes.map(scope => /*#__PURE__*/React.createElement(Chip, {
|
||||
key: scope.name,
|
||||
isReadOnly: true
|
||||
}, scope.displayName || scope.name)))), /*#__PURE__*/React.createElement(DataListCell, {
|
||||
key: 'pending-' + row,
|
||||
width: 2
|
||||
}, resource.shareRequests.length > 0 && /*#__PURE__*/React.createElement(ChipGroup, {
|
||||
categoryName: Msg.localize('pending')
|
||||
}, resource.shareRequests[0].scopes.map(scope => /*#__PURE__*/React.createElement(Chip, {
|
||||
key: scope.name,
|
||||
isReadOnly: true
|
||||
}, scope.displayName || scope.name))))]
|
||||
})))));
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=SharedResourcesTable.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+16
@@ -0,0 +1,16 @@
|
||||
export class Scope {
|
||||
constructor(name, displayName) {
|
||||
this.name = name;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
toString() {
|
||||
if (this.hasOwnProperty('displayName') && this.displayName) {
|
||||
return this.displayName;
|
||||
} else {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=resource-model.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/app/content/my-resources-page/resource-model.ts"],"names":["Scope","constructor","name","displayName","toString","hasOwnProperty"],"mappings":"AAeA,OAAO,MAAMA,KAAN,CAAY;AACVC,EAAAA,WAAW,CAAQC,IAAR,EAA6BC,WAA7B,EAAmD;AAAA,SAA3CD,IAA2C,GAA3CA,IAA2C;AAAA,SAAtBC,WAAsB,GAAtBA,WAAsB;AAAE;;AAEhEC,EAAAA,QAAQ,GAAW;AACtB,QAAI,KAAKC,cAAL,CAAoB,aAApB,KAAuC,KAAKF,WAAhD,EAA8D;AAC1D,aAAO,KAAKA,WAAZ;AACH,KAFD,MAEO;AACH,aAAO,KAAKD,IAAZ;AACH;AACJ;;AATgB","sourcesContent":["export interface Resource {\n _id: string;\n name: string;\n client: Client;\n scopes: Scope[];\n uris: string[];\n shareRequests: Permission[];\n}\n\nexport interface Client {\n baseUrl: string;\n clientId: string;\n name?: string;\n}\n\nexport class Scope {\n public constructor(public name: string, public displayName?: string) {}\n\n public toString(): string {\n if (this.hasOwnProperty('displayName') && (this.displayName)) {\n return this.displayName;\n } else {\n return this.name;\n }\n }\n}\n\nexport interface PaginatedResources {\n nextUrl: string;\n prevUrl: string;\n data: Resource[];\n}\n\nexport interface Permission {\n email?: string;\n firstName?: string;\n lastName?: string;\n scopes: Scope[] | string[]; // this should be Scope[] - fix API\n username: string;\n}\n\nexport interface Permissions {\n permissions: Permission[];\n row?: number;\n}\n"],"file":"resource-model.js"}
|
||||
Reference in New Issue
Block a user