diff --git a/src/components/DatePanel/index.js b/src/components/DatePanel/index.js
new file mode 100644
index 0000000..4e67908
--- /dev/null
+++ b/src/components/DatePanel/index.js
@@ -0,0 +1,25 @@
+/*
+ *
+ * Copyright 2018 Odysseus Data Services, inc.
+ * 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.
+ *
+ * Company: Odysseus Data Services, Inc.
+ * Product Owner/Architecture: Gregory Klebanov
+ * Authors: Pavel Grafkin, Alexander Saltykov, Vitaly Koulakov, Anton Gackovka, Alexandr Ryabokon, Mikhail Mironov
+ * Created: July 25, 2017
+ *
+ */
+
+import DatePanel from './presenter';
+
+export default DatePanel;
diff --git a/src/components/DatePanel/presenter.jsx b/src/components/DatePanel/presenter.jsx
new file mode 100644
index 0000000..fe7176b
--- /dev/null
+++ b/src/components/DatePanel/presenter.jsx
@@ -0,0 +1,96 @@
+/*
+ *
+ * Copyright 2018 Odysseus Data Services, inc.
+ * 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.
+ *
+ * Company: Odysseus Data Services, Inc.
+ * Product Owner/Architecture: Gregory Klebanov
+ * Authors: Pavel Grafkin, Alexander Saltykov, Vitaly Koulakov, Anton Gackovka, Alexandr Ryabokon, Mikhail Mironov
+ * Created: July 25, 2017
+ *
+ */
+
+import React, { Component, PropTypes } from "react";
+import BEMHelper from "services/BemHelper";
+import { Datepicker } from "arachne-ui-components";
+import * as moment from "moment";
+
+require("./style.scss");
+
+// NOTE: Datepicker requires DateInput to be a class
+/**
+ * @param {any} options.className
+ * @param {string} options.value Value passed by datepicker.
+ * @param {string} options.displayValue Value passed by parent component.
+ * @param {function} options.onClick Function that should be called to open datepicker.
+ */
+class DateInput extends Component {
+ render() {
+ const classes = new BEMHelper("study-date-input");
+ const { className, displayValue, onClick } = this.props;
+
+ // NOTE:
+ // We should be able to render custom caption (e.g., 'Empty'),
+ // that's why we cannot use value passed by datepicker which is always a date
+ return (
+
+
+ date_range
+
+ {displayValue}
+
+ );
+ }
+}
+
+DateInput.propTypes = {
+ className: PropTypes.any,
+ displayValue: PropTypes.string.isRequired,
+ onClick: PropTypes.func,
+};
+
+function DatePanel({ title, selected, dateFormat, minDate, maxDate, isEditable, onChange, className }) {
+ const classes = new BEMHelper("study-date-panel");
+ const displayDate = selected ? moment(selected).format(dateFormat) : "Empty";
+
+ return (
+
+ {title}
+ {isEditable ? (
+ }
+ minDate={minDate}
+ maxDate={maxDate}
+ onChange={onChange}
+ />
+ ) : (
+
+ )}
+
+ );
+}
+
+DatePanel.propTypes = {
+ dateFormat: PropTypes.string.isRequired,
+ isEditable: PropTypes.bool.isRequired,
+ maxDate: PropTypes.any,
+ minDate: PropTypes.any,
+ onChange: PropTypes.func,
+ selected: PropTypes.any,
+ title: PropTypes.string.isRequired,
+ className: PropTypes.string,
+};
+
+export default DatePanel;
diff --git a/src/components/DatePanel/style.scss b/src/components/DatePanel/style.scss
new file mode 100644
index 0000000..1e052cd
--- /dev/null
+++ b/src/components/DatePanel/style.scss
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright 2018 Odysseus Data Services, inc.
+ * 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.
+ *
+ * Company: Odysseus Data Services, Inc.
+ * Product Owner/Architecture: Gregory Klebanov
+ * Authors: Pavel Grafkin, Alexander Saltykov, Vitaly Koulakov, Anton Gackovka, Alexandr Ryabokon, Mikhail Mironov
+ * Created: July 25, 2017
+ *
+ */
+
+@import "styles/vars-and-mixins.scss";
+
+.#{$namespace} {
+ &study-date-panel {
+ display: flex;
+ align-items: center;
+ background: $white;
+ border-radius: $block-border-radius;
+ padding: 12px 20px;
+ @include block-shadow();
+
+ &__title {
+ @include title();
+ margin-right: auto;
+ }
+
+ &__picker {
+ cursor: pointer;
+ }
+ }
+
+ &study-date-input {
+ &__icon {
+ @include material-icon();
+ margin-right: 1rem;
+ }
+ display: flex;
+ align-items: center;
+ &__ico {
+ color: $grey-placeholder;
+ margin-right: 7px;
+ }
+ &__value {
+ }
+ }
+}
diff --git a/src/modules/Admin/actions/licenses.ts b/src/modules/Admin/actions/licenses.ts
index 358257f..873b168 100644
--- a/src/modules/Admin/actions/licenses.ts
+++ b/src/modules/Admin/actions/licenses.ts
@@ -60,10 +60,11 @@ function create(userId: number, vocabularyV4Ids: Array) {
});
}
-function resolve(id: number, accepted: boolean) {
+function resolve(id: number, accepted: boolean, expiredDate: any) {
return services.licenseAccept.create({
id,
accepted,
+ expiredDate,
});
}
diff --git a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/container.ts b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/container.ts
index f54c4bc..8c660b5 100644
--- a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/container.ts
+++ b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/container.ts
@@ -30,11 +30,14 @@ import { get, difference } from 'lodash';
import presenter from './presenter';
import selectors from './selectors';
import { VocabularyOption, User, Vocabulary } from 'modules/Admin/components/Licenses/types';
+import * as moment from 'moment';
+import { commonDateFormat } from 'const/formats';
interface IModalStateProps {
vocabularies: Array;
initialValues: {
vocabularies: Array;
+ expiredDates: Array;
};
user: User;
pendingVocabularies: Array;
@@ -43,7 +46,7 @@ interface IModalDispatchProps {
close: () => (dispatch: Function) => any;
remove: (id: string) => (dispatch: Function) => any;
loadLicenses: () => (dispatch: Function) => any;
- resolveLicense: (id: number, allow: boolean) => (dispatch: Function) => any;
+ resolveLicense: (id: number, allow: boolean, expiredDate: any) => (dispatch: Function) => any;
};
interface IModalProps extends IModalStateProps, IModalDispatchProps {
doSubmit: (vocabs: Array) => Promise;
@@ -58,6 +61,12 @@ class ModalEditPermissions extends Component {
function mapStateToProps(state: any): IModalStateProps {
const vocabularies = selectors.getVocabularies(state);
const pendingVocabularies = selectors.getPendingVocabularies(state);
+ const expiredDates = []
+ pendingVocabularies.forEach((vocab) => {
+ expiredDates[vocab.licenseId] = vocab.expiredDate ? moment(vocab.expiredDate).format() : moment(new Date().setFullYear(new Date().getFullYear() + 2)).format()
+ })
+
+
const user = get(state, 'modal.editPermission.data.user.name', {
id: -1,
name: 'Anonymous',
@@ -68,6 +77,7 @@ function mapStateToProps(state: any): IModalStateProps {
vocabularies,
initialValues: {
vocabularies: vocabularies.map(v => v.value.toString()),
+ expiredDates: expiredDates
},
user,
pendingVocabularies,
@@ -90,13 +100,13 @@ function mergeProps(
...stateProps,
...ownProps,
...dispatchProps,
- doSubmit: ({ vocabularies = [], pendingVocabs = [] }) => {
+ doSubmit: ({ vocabularies = [], pendingVocabs = [], expiredDates = [] }) => {
const promises = [];
difference(stateProps.initialValues.vocabularies, vocabularies).forEach((licenseId) => {
promises.push(dispatchProps.remove(licenseId));
});
pendingVocabs.forEach((isAllowed: boolean, licenseId: number) => {
- promises.push(dispatchProps.resolveLicense(licenseId, isAllowed));
+ promises.push(dispatchProps.resolveLicense(licenseId, isAllowed, expiredDates[licenseId]));
});
const promise = Promise.all(promises);
promise
diff --git a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/presenter.tsx b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/presenter.tsx
index 117ab20..a270500 100644
--- a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/presenter.tsx
+++ b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/presenter.tsx
@@ -20,97 +20,98 @@
*
*/
-import * as React from 'react';
-import BEMHelper from 'services/BemHelper';
-import {
- Modal,
- FormCheckboxList,
- Form,
- TabbedPane,
- RadioButton,
- Button,
-} from 'arachne-ui-components';
-import { Vocabulary } from 'modules/Admin/components/Licenses/types';
-import { Field } from 'redux-form';
+import * as React from "react";
+import BEMHelper from "services/BemHelper";
+import { Modal, FormCheckboxList, TabbedPane, RadioButton, Button } from "arachne-ui-components";
+import { Vocabulary } from "modules/Admin/components/Licenses/types";
+import { Field } from "redux-form";
+import DatePanel from "components/DatePanel";
+import { commonDateFormat } from "const/formats";
-require('./style.scss');
+require("./style.scss");
-function VocRadioButton ({ options, input }) {
- const classes = BEMHelper('pending-radio-btn');
+function VocRadioButton({ options, input }) {
+ const classes = BEMHelper("pending-radio-btn");
- return input.onChange(options.value)}
- />;
+ return (
+ input.onChange(options.value)}
+ />
+ );
+}
+
+function DatepickerControler({ options, input }) {
+ const classes = BEMHelper("date-picker");
+
+ return (
+
+ );
}
function ModalEditPermissions(props) {
- const {
- modal,
- vocabularies,
- user,
- doSubmit,
- pendingVocabularies,
- handleSubmit,
- } = props;
- const classes = BEMHelper('edit-permissions');
+ const { modal, vocabularies, user, doSubmit, pendingVocabularies, handleSubmit } = props;
+ const classes = BEMHelper("edit-permissions");
const sections = [
{
label: `Granted (${vocabularies.length})`,
- content:
-
-
,
+ content: (
+
+
+
+ ),
},
{
label: `Pending (${pendingVocabularies.length})`,
- content:
-
- {pendingVocabularies.map((voc: Vocabulary) =>
-
-
{voc.name}
-
-
-
-
-
-
+ content: (
+
+
+
+
Expired date
+
Allow
+
Forbid
- )}
-
+ {pendingVocabularies.map((voc: Vocabulary) => (
+
+
{voc.name}
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+ ),
},
];
return (
+ );
}
export default ModalEditPermissions;
diff --git a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/selectors.ts b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/selectors.ts
index ed1e4d7..823b609 100644
--- a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/selectors.ts
+++ b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/selectors.ts
@@ -23,6 +23,8 @@
import { createSelector } from 'reselect';
import { get } from 'lodash';
import { licenseStatuses } from 'const/vocabulary';
+import moment from 'moment';
+import { commonDateFormat } from 'const/formats';
const getRawVocs = (state: Object) => get(state, 'modal.editPermission.data.vocabularies', []) || [];
@@ -31,7 +33,7 @@ const getVocabularies = createSelector(
(rawResults: Array
) => rawResults
.filter(voc => voc.status === licenseStatuses.APPROVED)
.map((voc) => ({
- label: voc.code,
+ label: `${voc.code}${voc.expiredDate ? ' (Expired date: ' + moment(voc.expiredDate).format(commonDateFormat) + ')' : ''}`,
value: voc.licenseId,
})),
);
diff --git a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/style.scss b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/style.scss
index 95322e7..034baec 100644
--- a/src/modules/Admin/components/Licenses/components/ModalEditPermissions/style.scss
+++ b/src/modules/Admin/components/Licenses/components/ModalEditPermissions/style.scss
@@ -20,46 +20,60 @@
*
*/
-@import 'styles/vars-and-mixins.scss';
+@import "styles/vars-and-mixins.scss";
.#{$namespace} {
&edit-permissions {
- @include tabbed-modal();
+ @include tabbed-modal();
&__tab-content {
- padding: 2rem;
- min-width: 500px;
- min-height: 200px;
- }
+ padding: 2rem;
+ min-width: 500px;
+ min-height: 200px;
+ }
&__pending-voc {
- display: flex;
- padding: 0.5rem 0;
+ display: flex;
+ padding: 0.5rem 0;
}
&__pending-voc-name {
- flex-grow: 1;
- padding-right: 0.5rem;
+ //flex-grow: 1;
+
+ display: flex;
+ align-items: center;
+ width: 200px;
+ padding-right: 0.5rem;
}
&__pending-button {
- @include title();
- width: 6rem;
+ @include title();
+ width: 6rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__pending-date-picker {
+ @include title();
+ //width: 6rem;
+ margin-right: 20px;
+ width: 200px;
}
&__submit-button-wrapper {
- padding: 1rem 2rem;
+ padding: 1rem 2rem;
}
&__submit-button {
- width: 100%;
+ width: 100%;
}
}
&pending-radio-btn {
- & .ac-radio-button {
- &__box {
- margin: auto;
- }
- }
+ & .ac-radio-button {
+ &__box {
+ margin: auto;
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/modules/Admin/components/Statistics/components/Filters/presenter.tsx b/src/modules/Admin/components/Statistics/components/Filters/presenter.tsx
index 58f51a3..f0634ad 100644
--- a/src/modules/Admin/components/Statistics/components/Filters/presenter.tsx
+++ b/src/modules/Admin/components/Statistics/components/Filters/presenter.tsx
@@ -20,136 +20,147 @@
*
*/
-
-import * as React from 'react';
+import * as React from "react";
import BEMHelper from "services/BemHelper";
-import { Button, Form, FormDatepicker, FormInput, FormToggle, LoadingPanel } from 'arachne-ui-components';
+import { Button, Form, FormDatepicker, FormInput, FormToggle, LoadingPanel } from "arachne-ui-components";
import { commonDateFormat } from "const/formats";
import { SortingParams } from "modules/Admin/actions/statistics";
+import DatePanel from "components/DatePanel";
-require('./style.scss');
+require("./style.scss");
interface IStatisticsFilter {
- from: any,
- to: any,
- keywords?: string,
- licensedOnly?: boolean,
+ from: any;
+ to: any;
+ keywords?: string;
+ licensedOnly?: boolean;
}
-interface IStatisticsFilterProps extends IStatisticsFilterStateProps, IStatisticsFilterDispatchProps, IStatisticsFilterOwnProps {
- handleSubmit: Function
+interface IStatisticsFilterProps
+ extends IStatisticsFilterStateProps,
+ IStatisticsFilterDispatchProps,
+ IStatisticsFilterOwnProps {
+ handleSubmit: Function;
}
interface IStatisticsFilterDispatchProps {
- loadStatistics: Function
+ loadStatistics: Function;
}
interface IStatisticsFilterStateProps {
- isLoading: boolean,
- filter: IStatisticsFilter
+ isLoading: boolean;
+ filter: IStatisticsFilter;
}
interface IStatisticsFilterOwnProps {
- runSearch: (sorting?: SortingParams) => void,
- downloadCSV: Function
+ runSearch: (sorting?: SortingParams) => void;
+ downloadCSV: Function;
}
-function Filters(props: IStatisticsFilterProps) {
- const classes = BEMHelper('filters');
+function DatepickerControler({ options, input, titleDisplay }) {
+ const classes = BEMHelper("date-picker");
+
+ return (
+
+ );
+}
- const fields = [
- {
- name: 'keywords',
- InputComponent: {
- component: FormInput,
- props: {
- title: 'Keywords',
- placeholder: 'Keywords',
- type: 'text',
- },
- },
+function Filters(props: IStatisticsFilterProps) {
+ const classes = BEMHelper("filters");
+
+ const fields = [
+ {
+ name: "keywords",
+ InputComponent: {
+ component: FormInput,
+ props: {
+ title: "Keywords",
+ placeholder: "Keywords",
+ type: "text",
},
- {
- name: 'from',
- InputComponent: {
- component: FormDatepicker,
- props: {
- title: 'From',
- type: 'text',
- options: {
- selected: props.filter.from,
- dateFormat: commonDateFormat,
- },
- }
-
- }
+ },
+ },
+ {
+ name: "from",
+ InputComponent: {
+ component: DatepickerControler,
+ props: {
+ title: "From",
+ type: "text",
+ options: {
+ titleDisplay: "From",
+ selected: props.filter.from,
+ dateFormat: commonDateFormat,
+ },
},
- {
- name: 'to',
- InputComponent: {
- component: FormDatepicker,
- props: {
- title: 'To',
- type: 'text',
- options: {
- selected: props.filter.to,
- dateFormat: commonDateFormat,
- },
- }
-
- }
+ },
+ },
+ {
+ name: "to",
+ InputComponent: {
+ component: DatepickerControler,
+ props: {
+ title: "To",
+ type: "text",
+ options: {
+ titleDisplay: "To",
+ selected: props.filter.to,
+ dateFormat: commonDateFormat,
+ },
},
- {
- name: 'licensedOnly',
- InputComponent: {
- component: FormToggle,
- props: {
- label: 'License Only',
- }
-
- }
- }
- ];
- const submitBtn = {
- label: 'Show',
- loadingLabel: 'Loading...',
- mods: ['success', 'rounded'],
- };
-
- return (
-
-
-
-
-
-
-
- Export CSV
-
-
-
-
-
- );
+ },
+ },
+ {
+ name: "licensedOnly",
+ InputComponent: {
+ component: FormToggle,
+ props: {
+ label: "License Only",
+ },
+ },
+ },
+ ];
+ const submitBtn = {
+ label: "Show",
+ loadingLabel: "Loading...",
+ mods: ["success", "rounded"],
+ };
+
+ return (
+
+
+
+
+
+
+ Export CSV
+
+
+
+
+ );
}
export default Filters;
export {
- IStatisticsFilter,
- IStatisticsFilterStateProps,
- IStatisticsFilterDispatchProps,
- IStatisticsFilterProps,
- IStatisticsFilterOwnProps
-}
\ No newline at end of file
+ IStatisticsFilter,
+ IStatisticsFilterStateProps,
+ IStatisticsFilterDispatchProps,
+ IStatisticsFilterProps,
+ IStatisticsFilterOwnProps,
+};
diff --git a/src/modules/Admin/components/Statistics/components/Filters/style.scss b/src/modules/Admin/components/Statistics/components/Filters/style.scss
index 34dc7f1..99a35aa 100644
--- a/src/modules/Admin/components/Statistics/components/Filters/style.scss
+++ b/src/modules/Admin/components/Statistics/components/Filters/style.scss
@@ -20,18 +20,17 @@
*
*/
-@import 'styles/vars-and-mixins.scss';
+@import "styles/vars-and-mixins.scss";
.#{$namespace} {
&filters {
-
& form span {
- margin-bottom: 1rem;
+ // margin-bottom: 1rem;
}
& form input {
box-shadow: 1px -1px 3px 1px rgba(0, 0, 0, 0.1);
-
+ height: 44px;
}
&__export-button {
@@ -44,4 +43,4 @@
color: $white;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/modules/Vocabulary/actions/vocabularies.tsx b/src/modules/Vocabulary/actions/vocabularies.tsx
index 73589c3..421c06a 100644
--- a/src/modules/Vocabulary/actions/vocabularies.tsx
+++ b/src/modules/Vocabulary/actions/vocabularies.tsx
@@ -20,17 +20,18 @@
*
*/
-import API from 'services/Api';
-import services from '../apiServices';
+import API from "services/Api";
+import services from "../apiServices";
function load() {
return services.vocabularies.find();
}
-function requestLicense(vocabularyId) {
- return services.vocabLicenses.create({
- vocabularyId,
- });
+function requestLicense(vocabularyId, expiredDate) {
+ return services.vocabLicenses.create({
+ vocabularyId,
+ expiredDate,
+ });
}
export default {
diff --git a/src/modules/Vocabulary/components/DownloadHistory/container.ts b/src/modules/Vocabulary/components/DownloadHistory/container.ts
index e47035b..883c5a2 100644
--- a/src/modules/Vocabulary/components/DownloadHistory/container.ts
+++ b/src/modules/Vocabulary/components/DownloadHistory/container.ts
@@ -26,7 +26,7 @@ import actions from 'modules/Vocabulary/actions';
import { get } from 'lodash';
import { modal } from 'modules/Vocabulary/const';
import { ModalUtils } from 'arachne-ui-components';
-import presenter, { IDownloadRequest } from './presenter';
+import presenter, { IDownloadRequest, IVocabulary } from './presenter';
import selectors from './selectors';
import {
@@ -105,6 +105,7 @@ const mapDispatchToProps = {
checkAvailability: actions.download.checkBundleAvailability,
showRequestModal: (ids = [], message) => ModalUtils.actions.toggle(modal.licenses, true, { licenses: ids, message }),
showShareModal: (bundle) => ModalUtils.actions.toggle(modal.share, true, { bundle }),
+ openRequestModal: (vocab: IVocabulary) => ModalUtils.actions.toggle(modal.requestLicense, true, vocab),
};
function mergeProps(
diff --git a/src/modules/Vocabulary/components/DownloadHistory/presenter.tsx b/src/modules/Vocabulary/components/DownloadHistory/presenter.tsx
index 43e9c86..a36fa2d 100644
--- a/src/modules/Vocabulary/components/DownloadHistory/presenter.tsx
+++ b/src/modules/Vocabulary/components/DownloadHistory/presenter.tsx
@@ -20,33 +20,29 @@
*
*/
-import * as React from 'react';
-import {
- Button,
- LoadingPanel,
- Toolbar,
- Table,
- TableCellText,
-} from 'arachne-ui-components';
-import BEMHelper from 'services/BemHelper';
-import { paths, bundleStatuses } from 'modules/Vocabulary/const';
-import * as moment from 'moment';
-import {
- Accordion,
- AccordionItem,
-} from 'react-sanfona';
-import { fullDateFormat } from 'const/formats';
-import ModalEditNotifications from './components/ModalEditNotifications';
-import ModalRequestLicenses from './components/ModalRequestLicenses';
-import ModalShare from './components/ModalShare';
+import * as React from "react";
+import { Button, LoadingPanel, Toolbar, Table, TableCellText, Link } from "arachne-ui-components";
+import BEMHelper from "services/BemHelper";
+import { paths, bundleStatuses } from "modules/Vocabulary/const";
+import * as moment from "moment";
+import { Accordion, AccordionItem } from "react-sanfona";
+import { fullDateFormat } from "const/formats";
+import ModalEditNotifications from "./components/ModalEditNotifications";
+import ModalRequestLicenses from "./components/ModalRequestLicenses";
+import ModalShare from "./components/ModalShare";
+// import { HISTORY } from "./const";
+import { licenseStatuses } from "const/vocabulary";
+import { Vocabulary } from "../List/components/Results/selectors";
+import ModalRequestLicense from "../List/components/ModalRequestLicense";
-require('./style.scss');
+require("./style.scss");
interface IVocabulary {
id: number;
code: string;
name: string;
cdmVersion: string;
+ expiredDate?: string;
}
interface IDownloadRequest {
@@ -57,19 +53,19 @@ interface IDownloadRequest {
cdmVersion: number;
name: string;
status: string;
-};
+}
interface IHistoryItem extends IVocabulary {
date?: string;
link?: string;
tableRowClass: string;
-};
+}
interface IDownloadHistoryStateProps {
isLoading: boolean;
- history: Array,
+ history: Array;
currentUser: string;
-};
+}
interface IDownloadHistoryDispatchProps {
load: () => (dispatch: Function) => any;
@@ -80,88 +76,112 @@ interface IDownloadHistoryDispatchProps {
checkAvailability: Function;
showRequestModal: Function;
showShareModal: Function;
-};
+ openRequestModal: Function;
+}
interface IDownloadHistoryProps extends IDownloadHistoryStateProps, IDownloadHistoryDispatchProps {
removeBundle: (id: number) => any;
restoreBundle: (id: number) => any;
download: (bundle: IDownloadRequest) => any;
-};
+}
interface IDownloadHistoryStatefulProps {
toggle: (id: number) => any;
expandedBundleId: number;
-};
+}
+
+function CellLicense(props: any) {
+ const { className, value, openRequestModal, isPending, isCheckable, notAvailable } = props;
+ const classes = BEMHelper("cell-license");
+ if (!value) {
+ return null;
+ }
+ if (isCheckable) {
+ return {value} ;
+ } else if (isPending) {
+ return (
+
+ timer {value}
+
+ );
+ } else {
+ return (
+ {
+ if (notAvailable) {
+ return false;
+ }
+ openRequestModal();
+ }}
+ >
+ vpn_key
+ {value}
+
+ );
+ }
+}
function BundleName({ name, date, onClick, isOpened, releaseVersion, downloadShareDTO, currentUser }) {
const dateFormat = fullDateFormat;
- const classes = BEMHelper('bundle-caption');
+ const classes = BEMHelper("bundle-caption");
const isAlreadyShared = downloadShareDTO && downloadShareDTO.ownerUsername === currentUser;
- return
-
keyboard_arrow_right
-
- {name}
- {moment(date).format(dateFormat)}
- {releaseVersion}
- {downloadShareDTO && !isAlreadyShared && Shared by {downloadShareDTO.ownerUsername} }
-
-
;
+ return (
+
+
keyboard_arrow_right
+
+ {name}
+ {moment(date).format(dateFormat)}
+ {releaseVersion}
+ {downloadShareDTO && !isAlreadyShared && Shared by {downloadShareDTO.ownerUsername} }
+
+
+ );
}
function BundleTitle({ bundle, removeBundle, toggle, isExpanded, restore, download, share, showShareModal, currentUser }) {
- const classes = BEMHelper('download-history');
+ const classes = BEMHelper("download-history");
const isAlreadyShared = bundle.downloadShareDTO && bundle.downloadShareDTO.ownerUsername === currentUser;
const isShareable = isAlreadyShared || !bundle.downloadShareDTO;
- const shareBtnTitle = isAlreadyShared ? 'Edit share' : !bundle.downloadShareDTO ? 'Share' : '';
- return toggle(bundle.id)} isOpened={isExpanded} currentUser={currentUser} />}
- >
- {[bundleStatuses.READY].includes(bundle.status)
- ?
-
download(bundle)}
- mods={['rounded']}
- >
+ const shareBtnTitle = isAlreadyShared ? "Edit share" : !bundle.downloadShareDTO ? "Share" : "";
+ return (
+ toggle(bundle.id)} isOpened={isExpanded} currentUser={currentUser} />}>
+ {[bundleStatuses.READY].includes(bundle.status) ? (
+
+ download(bundle)} mods={["rounded"]}>
Download
{isShareable && (
- showShareModal(bundle)}
- mods={['rounded']}
- >
- {shareBtnTitle}
-
+ showShareModal(bundle)} mods={["rounded"]}>
+ {shareBtnTitle}
+
)}
{isShareable && (
- removeBundle(bundle.id)}
- >
+ removeBundle(bundle.id)}>
Archive
)}
-
- :
- {bundle.status}
- {bundle.status === bundleStatuses.ARCHIVED && isShareable &&
- restore(bundle.id)}
- >
- Restore
-
- }
-
- }
- ;
+
+ ) : (
+
+ {bundle.status}
+ {bundle.status === bundleStatuses.ARCHIVED && isShareable && (
+ restore(bundle.id)}>
+ Restore
+
+ )}
+
+ )}
+
+ );
}
function VocabsList(props: IDownloadHistoryProps & IDownloadHistoryStatefulProps) {
const {
+ load,
isLoading,
history,
removeBundle,
@@ -169,84 +189,80 @@ function VocabsList(props: IDownloadHistoryProps & IDownloadHistoryStatefulProps
expandedBundleId,
restoreBundle,
share,
- load,
showNotifications,
showShareModal,
download,
currentUser,
+ openRequestModal = () => {},
} = props;
- const classes = BEMHelper('download-history');
-
+ const classes = BEMHelper("download-history");
+ // const history: IDownloadRequest[] = HISTORY;
return (
-
- Refresh
- Notifications
+
+
+ Refresh
+
+
+ Notifications
+
- {history && history.map((bundle: IDownloadRequest, index: number) =>
- }
- {...classes('bundle-caption')}
- key={`caption${index}`}
- slug={bundle.id}
- >
-
- (
+
-
-
-
+
+
+
+
+
+ ({
+ className: classes({
+ element: "cell",
+ modifiers: {
+ selected: vocab.isChecked,
+ },
+ }).className,
+ isPending: vocab.status === licenseStatuses.PENDING,
+ openRequestModal: () => openRequestModal(vocab),
+ isCheckable: vocab.isCheckable,
+ notAvailable: vocab.required === "Currently not available",
+ })}
/>
-
-
- )}
+
+
+
+ ))}
+
);
}
export default VocabsList;
-export {
- IDownloadHistoryStateProps,
- IDownloadHistoryDispatchProps,
- IDownloadHistoryProps,
- IHistoryItem,
- IDownloadRequest,
- IVocabulary,
-};
+export { IDownloadHistoryStateProps, IDownloadHistoryDispatchProps, IDownloadHistoryProps, IHistoryItem, IDownloadRequest, IVocabulary };
diff --git a/src/modules/Vocabulary/components/DownloadHistory/selectors.ts b/src/modules/Vocabulary/components/DownloadHistory/selectors.ts
index 10e0789..ec69933 100644
--- a/src/modules/Vocabulary/components/DownloadHistory/selectors.ts
+++ b/src/modules/Vocabulary/components/DownloadHistory/selectors.ts
@@ -17,28 +17,29 @@
* Product Owner/Architecture: Gregory Klebanov
* Authors: Alexandr Saltykov, Pavel Grafkin, Vitaly Koulakov, Anton Gackovka
* Created: March 3, 2017
- *
+ *
*/
-import { createSelector } from 'reselect';
-import { get } from 'lodash';
-import * as moment from 'moment';
-import BEMHelper from 'services/BemHelper';
-import { IDownloadRequest, IVocabulary, IHistoryItem } from './presenter';
+import { createSelector } from "reselect";
+import { get } from "lodash";
+import * as moment from "moment";
+import BEMHelper from "services/BemHelper";
+import { IDownloadRequest, IVocabulary, IHistoryItem } from "./presenter";
+import { commonDateFormat } from "const/formats";
-const getRawHistory = (state: Object) => get(state, 'vocabulary.history.queryResult') || [];
+const getRawHistory = (state: Object) => get(state, "vocabulary.history.queryResult") || [];
-const getHistory = createSelector(
- getRawHistory,
- (rawResults: Array) => rawResults.map((bundle: IDownloadRequest) => ({
- ...bundle,
- vocabularies: bundle.vocabularies.map((voc: IVocabulary) => ({
- ...voc,
- cdmVersion: `CDM ${bundle.cdmVersion}`,
- }))
+const getHistory = createSelector(getRawHistory, (rawResults: Array) =>
+ rawResults.map((bundle: IDownloadRequest) => ({
+ ...bundle,
+ vocabularies: bundle.vocabularies.map((voc: IVocabulary) => ({
+ ...voc,
+ cdmVersion: `CDM ${bundle.cdmVersion}`,
+ expiredDate: voc.expiredDate ? moment(voc.expiredDate).format(commonDateFormat) : "",
})),
- );
+ }))
+);
export default {
getHistory,
-};
\ No newline at end of file
+};
diff --git a/src/modules/Vocabulary/components/DownloadHistory/style.scss b/src/modules/Vocabulary/components/DownloadHistory/style.scss
index e363118..95dd189 100644
--- a/src/modules/Vocabulary/components/DownloadHistory/style.scss
+++ b/src/modules/Vocabulary/components/DownloadHistory/style.scss
@@ -91,7 +91,11 @@
}
&__name-th {
- width: 70%;
+ width: 40%;
+ }
+
+ &__expiredDate-th {
+ width: 20%;
}
&__bundle-caption {
diff --git a/src/modules/Vocabulary/components/List/components/ModalRequestLicense/container.ts b/src/modules/Vocabulary/components/List/components/ModalRequestLicense/container.ts
index 7a978e7..d4e6133 100644
--- a/src/modules/Vocabulary/components/List/components/ModalRequestLicense/container.ts
+++ b/src/modules/Vocabulary/components/List/components/ModalRequestLicense/container.ts
@@ -20,34 +20,34 @@
*
*/
-import { Component } from 'react';
-import { connect } from 'react-redux';
-import actions from 'modules/Vocabulary/actions';
-import { ModalUtils } from 'arachne-ui-components';
-import { modal } from 'modules/Vocabulary/const';
-import { licenseStatuses } from 'const/vocabulary';
-import { get } from 'lodash';
-import presenter from './presenter';
-import {
- Vocabulary,
-} from '../Results/selectors';
+import { Component } from "react";
+import { connect } from "react-redux";
+import actions from "modules/Vocabulary/actions";
+import { ModalUtils } from "arachne-ui-components";
+import { forms, modal } from "modules/Vocabulary/const";
+import { licenseStatuses } from "const/vocabulary";
+import { get } from "lodash";
+import presenter, { IModalDispatchProps, IModalProps, IModalStateProps } from "./presenter";
+import { Vocabulary } from "../Results/selectors";
+import { reduxForm } from "redux-form";
+import * as moment from "moment";
-interface IModalStateProps {
- vocab: Vocabulary;
- isLoading: boolean;
-};
+// interface IModalStateProps {
+// vocab: Vocabulary;
+// isLoading: boolean;
+// }
-interface IModalDispatchProps {
- close: () => null;
- requestLicense: (id: number) => Promise;
- openConfirmModal: Function;
- loadList: Function;
-};
+// interface IModalDispatchProps {
+// close: () => null;
+// requestLicense: (id: number, expiredDate: any) => Promise;
+// openConfirmModal: Function;
+// loadList: Function;
+// }
-interface IModalProps extends IModalStateProps, IModalDispatchProps {
- modal: string;
- request: Function;
-};
+// interface IModalProps extends IModalStateProps, IModalDispatchProps {
+// modal: string;
+// request: Function;
+// }
class ModalRequestLicense extends Component {
render() {
@@ -55,25 +55,49 @@ class ModalRequestLicense extends Component {
}
}
+const getStatisticExpiredDateValue = (state, expiredDate) => {
+ let _expiredDate;
+ if (expiredDate) {
+ const expiredDateTS = new Date(moment(expiredDate).format()).getTime();
+ const currentDateTS = new Date().getTime();
+ if (expiredDateTS <= currentDateTS) {
+ _expiredDate = moment();
+ } else {
+ _expiredDate = moment(expiredDate);
+ }
+ } else {
+ _expiredDate = moment();
+ }
+ return get(state, "form.requestLinsence.values", {
+ expiredDate: _expiredDate,
+ });
+};
+
function mapStateToProps(state: any): IModalStateProps {
- const vocab: Vocabulary = get(state, 'modal.requestLicense.data', {
+ const vocab: Vocabulary = get(state, "modal.requestLicense.data", {
id: -1,
- code: '',
- name: 'Unnamed vocabulary',
+ code: "",
+ name: "Unnamed vocabulary",
available: true,
- update: '',
+ update: "",
index: 0,
isCheckable: false,
isChecked: false,
- tableRowClass: '',
+ tableRowClass: "",
status: licenseStatuses.APPROVED,
clickDefault: false,
+ expiredDate: "",
+ typeModal: "",
});
- const isLoading = get(state, 'vocabulary.vocabLicenses.isSaving', false);
-
- return {
+ const isLoading = get(state, "vocabulary.vocabLicenses.isSaving", false);
+ const expiredDate = getStatisticExpiredDateValue(state, vocab.expiredDate).expiredDate;
+ return {
vocab,
isLoading,
+ expiredDate,
+ initialValues: {
+ expiredDate,
+ },
};
}
@@ -82,32 +106,41 @@ const mapDispatchToProps = {
requestLicense: actions.vocabularies.requestLicense,
openConfirmModal: () => ModalUtils.actions.toggle(modal.confirmLicense, true),
loadList: actions.vocabularies.load,
+ loadHistory: actions.history.load,
};
-function mergeProps(
- stateProps: IModalStateProps,
- dispatchProps: IModalDispatchProps,
- ownProps
- ): IModalProps {
+function mergeProps(stateProps: IModalStateProps, dispatchProps: IModalDispatchProps, ownProps): IModalProps {
return {
...stateProps,
...ownProps,
...dispatchProps,
- request: () => {
- return dispatchProps.requestLicense(stateProps.vocab.id)
+ request: (expiredDate, isHistoryScreen) => {
+ return dispatchProps
+ .requestLicense(stateProps.vocab.id, expiredDate)
.then(() => dispatchProps.close())
.then(() => dispatchProps.openConfirmModal())
- .then(() => dispatchProps.loadList())
+ .then(() => {
+ if (isHistoryScreen) {
+ dispatchProps.loadHistory();
+ } else {
+ dispatchProps.loadList();
+ }
+ })
.catch(() => {});
},
};
}
-const ReduxModalWindow = ModalUtils.connect({ name: modal.requestLicense })(ModalRequestLicense);
+const ModalRequestLicenseForm = reduxForm({
+ form: forms.requestLinsence,
+ onSubmit: () => {
+ console.log("onSubmit");
+ },
+})(ModalRequestLicense);
+const ReduxModalWindow = ModalUtils.connect({ name: modal.requestLicense })(ModalRequestLicenseForm);
export default connect(
- mapStateToProps,
- mapDispatchToProps,
- mergeProps
-)
-(ReduxModalWindow);
+ mapStateToProps,
+ mapDispatchToProps,
+ mergeProps
+)(ReduxModalWindow);
diff --git a/src/modules/Vocabulary/components/List/components/ModalRequestLicense/presenter.tsx b/src/modules/Vocabulary/components/List/components/ModalRequestLicense/presenter.tsx
index fb782e7..ed3b80f 100644
--- a/src/modules/Vocabulary/components/List/components/ModalRequestLicense/presenter.tsx
+++ b/src/modules/Vocabulary/components/List/components/ModalRequestLicense/presenter.tsx
@@ -20,45 +20,115 @@
*
*/
-import * as React from 'react';
-import BEMHelper from 'services/BemHelper';
-import { Modal, Button, LoadingPanel } from 'arachne-ui-components';
-import {
- Vocabulary,
-} from '../Results/selectors';
+import * as React from "react";
+import BEMHelper from "services/BemHelper";
+import { Modal, Button, LoadingPanel } from "arachne-ui-components";
+import { Vocabulary } from "../Results/selectors";
+import { commonDateFormat } from "const/formats";
+import { Field } from "redux-form";
+import { paths, TYPE_MODAL } from "modules/Vocabulary/const";
+import DatePanel from "components/DatePanel";
-require('./style.scss');
+require("./style.scss");
-interface IModalProps {
- modal: string;
- request: Function;
- vocab: Vocabulary;
- isLoading: boolean;
-};
+interface IModalStateProps {
+ vocab: Vocabulary;
+ isLoading: boolean;
+ expiredDate: any;
+ initialValues: {
+ expiredDate: string;
+ };
+}
+
+interface IModalDispatchProps {
+ close: () => null;
+ requestLicense: (id: number, expiredDate: any) => Promise;
+ openConfirmModal: Function;
+ loadList: Function;
+ loadHistory: Function;
+}
+
+interface IModalProps extends IModalStateProps, IModalDispatchProps {
+ modal: string;
+ request: Function;
+ vocab: Vocabulary;
+ isLoading: boolean;
+}
+
+// interface IReduxFieldProps {
+// options: any;
+// input: any;
+// }
+
+function DatepickerControler({ options, input, titleDisplay }) {
+ const classes = BEMHelper("date-picker");
+
+ return (
+
+ );
+}
function ModalConfirmDownload(props: IModalProps) {
- const {
- modal,
- request,
- vocab,
- isLoading,
- } = props;
- const classes = BEMHelper('request-license');
+ const { modal, request, vocab, isLoading, expiredDate } = props;
+ const classes = BEMHelper("request-license");
+ const getContextModal = () => {
+ switch (vocab.typeModal) {
+ case TYPE_MODAL.UPDATE_LICENSE:
+ return {
+ modalTitle: "Extend License",
+ buttonLabel: "Request Extension",
+ titleDatePicker: "New expiration date",
+ modalMessage: "",
+ };
+ case TYPE_MODAL.REQUEST_LICENSE:
+ default:
+ return {
+ modalTitle: "Request access",
+ buttonLabel: "Request",
+ titleDatePicker: "License Expiration Date",
+ modalMessage: (
+
+ {`Vocabulary '${vocab.name}' requires a license`}
+
+
+ ),
+ };
+ }
+ };
+ const { modalTitle, buttonLabel, titleDatePicker, modalMessage } = getContextModal();
+
+ const isHistoryScreen = window.location.pathname === paths.history();
return (
-
-
- Vocabulary '{vocab.name}' requires a license
-
- Request
-
-
-
- );
+
+
+ {modalMessage}
+ {/* Vocabulary '{vocab.name}' requires a license
*/}
+
+ }
+ name="expiredDate"
+ />
+
+
request(expiredDate, isHistoryScreen)}
+ mods={["submit", "rounded"]}
+ >
+ {buttonLabel}
+
+
+
+
+ );
}
export default ModalConfirmDownload;
+export { IModalProps, IModalStateProps, IModalDispatchProps };
diff --git a/src/modules/Vocabulary/components/List/components/ModalRequestLicense/style.scss b/src/modules/Vocabulary/components/List/components/ModalRequestLicense/style.scss
index 1e59c9d..bdd623c 100644
--- a/src/modules/Vocabulary/components/List/components/ModalRequestLicense/style.scss
+++ b/src/modules/Vocabulary/components/List/components/ModalRequestLicense/style.scss
@@ -20,15 +20,23 @@
*
*/
-@import 'styles/vars-and-mixins.scss';
+@import "styles/vars-and-mixins.scss";
.#{$namespace} {
&request-license {
min-width: 500px;
+ &__request-date {
+ width: 100%;
+ }
+
&__request-button {
- margin-top: 2rem;
+ margin-top: 1rem;
width: 100%;
}
}
-}
\ No newline at end of file
+
+ &date-picker {
+ display: block;
+ }
+}
diff --git a/src/modules/Vocabulary/components/List/components/Results/container.ts b/src/modules/Vocabulary/components/List/components/Results/container.ts
index 0ea004c..8a2bf70 100644
--- a/src/modules/Vocabulary/components/List/components/Results/container.ts
+++ b/src/modules/Vocabulary/components/List/components/Results/container.ts
@@ -20,27 +20,20 @@
*
*/
-import { connect } from 'react-redux';
-import { Component } from 'react';
-import actions from 'modules/Vocabulary/actions';
-import { apiPaths, forms, modal } from 'modules/Vocabulary/const';
-import { get } from 'lodash';
-import { push as goToPage } from 'react-router-redux';
-import { reduxForm, reset, FormProps, change as reduxFormChange } from 'redux-form';
-import { ModalUtils } from 'arachne-ui-components';
-import { isEmpty } from 'lodash';
-import presenter from './presenter';
-import selectors from './selectors';
+import { connect } from "react-redux";
+import { Component } from "react";
+import actions from "modules/Vocabulary/actions";
+import { apiPaths, forms, modal, TYPE_MODAL } from "modules/Vocabulary/const";
+import { get } from "lodash";
+import { push as goToPage } from "react-router-redux";
+import { reduxForm, reset, FormProps, change as reduxFormChange } from "redux-form";
+import { ModalUtils } from "arachne-ui-components";
+import { isEmpty } from "lodash";
+import presenter from "./presenter";
+import selectors from "./selectors";
-import {
- IResultsStateProps,
- IResultsDispatchProps,
- IResultsProps,
- IResultsOwnProps,
-} from './presenter';
-import {
- Vocabulary,
-} from './selectors';
+import { IResultsStateProps, IResultsDispatchProps, IResultsProps, IResultsOwnProps } from "./presenter";
+import { Vocabulary } from "./selectors";
class Results extends Component & IResultsOwnProps, void> {
render() {
@@ -54,7 +47,7 @@ function mapStateToProps(state: Object, ownProps: any): IResultsStateProps {
vocabulary: [],
};
// top checkbox is checked
- let areAllChecked = get(state, 'vocabulary.download.data.allChecked');
+ let areAllChecked = get(state, "vocabulary.download.data.allChecked");
vocabularies.forEach((vocabulary) => {
if (areAllChecked === true) {
initialValues.vocabulary[`${vocabulary.id}`] = vocabulary.isCheckable;
@@ -68,15 +61,15 @@ function mapStateToProps(state: Object, ownProps: any): IResultsStateProps {
if (!isEmpty(ownProps.predefinedVocabs)) {
initialValues.vocabulary = [];
- ownProps.predefinedVocabs.forEach(vocabId => {
+ ownProps.predefinedVocabs.forEach((vocabId) => {
initialValues.vocabulary[vocabId] = true;
});
}
const values = get(state, `form.${forms.download}.values.vocabulary`, []) || [];
- const selection = get(state, `form.${forms.downloadSettings}.values.selection`, 'all');
- if (selection !== 'all') {
+ const selection = get(state, `form.${forms.downloadSettings}.values.selection`, "all");
+ if (selection !== "all") {
vocabularies = vocabularies.filter((v: Vocabulary) => get(values, `${v.id}`, false));
}
@@ -94,7 +87,7 @@ function mapStateToProps(state: Object, ownProps: any): IResultsStateProps {
areAllChecked,
areAllRowsChecked,
initialValues,
- sorting: '',
+ sorting: "",
vocabularies,
};
}
@@ -103,7 +96,8 @@ const mapDispatchToProps = {
unselectAll: () => reset(forms.download),
toggleAll: actions.download.toggleAllVocabs,
toggle: (id: number, state: boolean) => reduxFormChange(forms.download, `vocabulary[${id}]`, state),
- openRequestModal: (vocab: Vocabulary) => ModalUtils.actions.toggle(modal.requestLicense, true, vocab),
+ openRequestModal: (vocab: Vocabulary, typeModal?: string) =>
+ ModalUtils.actions.toggle(modal.requestLicense, true, { ...vocab, typeModal: typeModal || TYPE_MODAL.REQUEST_LICENSE }),
};
function mergeProps(
@@ -114,9 +108,7 @@ function mergeProps(
return {
...stateProps,
...dispatchProps,
- setSorting: () => {
-
- },
+ setSorting: () => {},
toggleAllCheckboxes: () => dispatchProps.toggleAll(!stateProps.areAllChecked),
};
}
diff --git a/src/modules/Vocabulary/components/List/components/Results/presenter.tsx b/src/modules/Vocabulary/components/List/components/Results/presenter.tsx
index 6d9e418..c621b01 100644
--- a/src/modules/Vocabulary/components/List/components/Results/presenter.tsx
+++ b/src/modules/Vocabulary/components/List/components/Results/presenter.tsx
@@ -20,34 +20,29 @@
*
*/
-import * as React from 'react';
-import BEMHelper from 'services/BemHelper';
-import {
- Button,
- Table,
- TableCellText as Cell,
- Checkbox,
- Link,
-} from 'arachne-ui-components';
-import { push } from 'react-router-redux';
-import { Field, FormProps } from 'redux-form';
-import { licenseStatuses } from 'const/vocabulary';
-import { Vocabulary } from './selectors';
-
-require('./style.scss');
+import * as React from "react";
+import BEMHelper from "services/BemHelper";
+import { Table, TableCellText as Cell, Checkbox, Link } from "arachne-ui-components";
+import { Field, FormProps } from "redux-form";
+import { licenseStatuses } from "const/vocabulary";
+import { Vocabulary } from "./selectors";
+import { TYPE_MODAL } from "modules/Vocabulary/const";
+// import { VOCABULARY } from './const';
+
+require("./style.scss");
interface IDownloadCheckboxProps {
options: {
className: string;
};
input: any;
-};
+}
interface ICellProps {
className: string;
isCheckable: boolean;
name: string;
-};
+}
interface IResultsStateProps {
areAllChecked: boolean | Object;
@@ -55,128 +50,148 @@ interface IResultsStateProps {
sorting: string;
vocabularies: Array;
initialValues: Object;
-};
+}
interface IResultsDispatchProps {
toggleAll: (on: boolean) => (dispatch: Function) => any;
toggle: (id: number, on: boolean) => (dispatch: Function) => any;
openRequestModal: Function;
-};
+}
interface IResultsProps extends IResultsStateProps, IResultsDispatchProps {
toggleAllCheckboxes: () => (dispatch: Function) => any;
setSorting: Function;
-};
+}
interface IResultsOwnProps {
predefinedVocabs: Array;
-};
+}
function DownloadCheckbox(props: IDownloadCheckboxProps) {
const { options, /*redux-form*/ input } = props;
- return ( );
+ return ;
}
function CellChecked(props: any) {
const { className, isCheckable, name } = props;
-
- return isCheckable
- ?
- : null;
+ const classes = BEMHelper("cell-checked");
+
+ return isCheckable ? (
+
+ ) : (
+
+ License Expired
+
+ );
}
function CellLicense(props: any) {
const { className, value, openRequestModal, isPending, isCheckable, notAvailable } = props;
- const classes = BEMHelper('cell-license');
+ const classes = BEMHelper("cell-license");
if (!value) {
return null;
}
if (isCheckable) {
return {value} ;
} else if (isPending) {
- return
-
- timer
- {value}
- ;
+ return (
+
+ timer {value}
+
+ );
} else {
- return {
- if (notAvailable) {
- return false;
- }
- openRequestModal();
- }}>
-
- vpn_key
-
+ return (
+ {
+ if (notAvailable) {
+ return false;
+ }
+ openRequestModal();
+ }}
+ >
+ vpn_key
{value}
- ;
+
+ );
}
+}
+function CellLicenseExpiredDate(props: any) {
+ const { className, value, openRequestModal } = props;
+ const classes = BEMHelper("cell-license");
+
+ return (
+ {
+ if (!value) return;
+ openRequestModal();
+ }}
+ >
+ {value}
+
+ );
}
function Results(props: IResultsProps & FormProps<{}, {}, {}>) {
- const {
- areAllRowsChecked,
- vocabularies,
- sorting,
- setSorting,
- toggleAllCheckboxes,
- toggle,
- openRequestModal,
- } = props;
- const classes = BEMHelper('vocabularies');
+ const { areAllRowsChecked, vocabularies, sorting, setSorting, toggleAllCheckboxes, toggle, openRequestModal } = props;
+ // let vocabularies: any = VOCABULARY
+ const classes = BEMHelper("vocabularies");
const selectAllButton = ;
// add modifiers for Table component
vocabularies.map((vocabulary) => {
if (vocabulary.isChecked) {
- vocabulary.tableRowClass = classes('selected-row').className;
+ vocabulary.tableRowClass = classes("selected-row").className;
}
});
+ console.log("vocabularies", vocabularies);
return (
{
- if(vocab.isCheckable) {
- toggle(vocab.id, !vocab.isChecked);
- }
+ if (vocab.isCheckable) {
+ toggle(vocab.id, !vocab.isChecked);
}
- }
+ }}
>
({
isCheckable: vocab.isCheckable,
name: `vocabulary[${vocab.id}]`,
className: classes({
- element: 'cell',
+ element: "cell",
modifiers: {
unclickable: vocab.isCheckable,
},
}).className,
})}
- />
+ />
({
+ {...classes("id")}
+ header="ID (CDM v4.5)"
+ field="id"
+ props={(vocab: Vocabulary) => ({
className: classes({
- element: 'cell',
+ element: "cell",
modifiers: {
selected: vocab.isChecked,
},
@@ -184,12 +199,12 @@ function Results(props: IResultsProps & FormProps<{}, {}, {}>) {
})}
/>
({
+ {...classes("code")}
+ header="CODE (CDM v5)"
+ field="code"
+ props={(vocab: Vocabulary) => ({
className: classes({
- element: 'cell',
+ element: "cell",
modifiers: {
selected: vocab.isChecked,
},
@@ -197,12 +212,12 @@ function Results(props: IResultsProps & FormProps<{}, {}, {}>) {
})}
/>
({
+ {...classes("name")}
+ header="Name"
+ field="name"
+ props={(vocab: Vocabulary) => ({
className: classes({
- element: 'cell',
+ element: "cell",
modifiers: {
selected: vocab.isChecked,
},
@@ -210,29 +225,44 @@ function Results(props: IResultsProps & FormProps<{}, {}, {}>) {
})}
/>
({
+ {...classes("required")}
+ header="Required"
+ field="required"
+ props={(vocab: Vocabulary) => ({
className: classes({
- element: 'cell',
+ element: "cell",
modifiers: {
selected: vocab.isChecked,
},
}).className,
isPending: vocab.status === licenseStatuses.PENDING,
- openRequestModal: () => openRequestModal(vocab),
+ openRequestModal: () => openRequestModal(vocab, TYPE_MODAL.REQUEST_LICENSE),
isCheckable: vocab.isCheckable,
- notAvailable: vocab.required === 'Currently not available',
+ notAvailable: vocab.required === "Currently not available",
+ })}
+ />
+
+ ({
+ className: classes({
+ element: "cell",
+ modifiers: {
+ selected: vocab.isChecked,
+ },
+ }).className,
+ openRequestModal: () => openRequestModal(vocab, TYPE_MODAL.UPDATE_LICENSE),
})}
/>
({
+ {...classes("update")}
+ header="Latest Update"
+ field="update"
+ props={(vocab: Vocabulary) => ({
className: classes({
- element: 'cell',
+ element: "cell",
modifiers: {
selected: vocab.isChecked,
},
@@ -245,9 +275,4 @@ function Results(props: IResultsProps & FormProps<{}, {}, {}>) {
}
export default Results;
-export {
- IResultsStateProps,
- IResultsDispatchProps,
- IResultsProps,
- IResultsOwnProps,
-};
+export { IResultsStateProps, IResultsDispatchProps, IResultsProps, IResultsOwnProps };
diff --git a/src/modules/Vocabulary/components/List/components/Results/selectors.ts b/src/modules/Vocabulary/components/List/components/Results/selectors.ts
index fd25622..760510e 100644
--- a/src/modules/Vocabulary/components/List/components/Results/selectors.ts
+++ b/src/modules/Vocabulary/components/List/components/Results/selectors.ts
@@ -38,6 +38,8 @@ interface Vocabulary {
status: string;
clickDefault: boolean;
required?: string;
+ expiredDate: string;
+ typeModal: string;
};
const getRawVocabs = (state: Object) => get(state, 'vocabulary.vocabularies.queryResult') || [];
@@ -47,7 +49,9 @@ const getVocabs = createSelector(
(rawResults: Array) => rawResults.map((vocabulary: Vocabulary, index: number) => ({
...vocabulary,
update: vocabulary.update ? moment(vocabulary.update).format(commonDateFormat) : '',
+ expiredDate: vocabulary.expiredDate ? moment(vocabulary.expiredDate).format(commonDateFormat) : '',
isChecked: false,
+ typeModal: '',
isCheckable: vocabulary.available === true,
// for redux-form
index,
diff --git a/src/modules/Vocabulary/components/List/components/Results/style.scss b/src/modules/Vocabulary/components/List/components/Results/style.scss
index c905a62..2762646 100644
--- a/src/modules/Vocabulary/components/List/components/Results/style.scss
+++ b/src/modules/Vocabulary/components/List/components/Results/style.scss
@@ -20,7 +20,7 @@
*
*/
-@import 'styles/vars-and-mixins.scss';
+@import "styles/vars-and-mixins.scss";
.#{$namespace} {
&vocabularies {
@@ -43,7 +43,7 @@
width: 10%;
}
&__name-th {
- width: 50%;
+ width: 37.5%;
}
&__required-th {
width: 12.5%;
@@ -51,11 +51,14 @@
&__update-th {
width: 12.5%;
}
+ &__expiredDate-th {
+ width: 12.5%;
+ }
&__selected-row {
background: $grey-light;
}
-
+
&__cell {
&--disabled {
@include material-icon();
@@ -94,4 +97,15 @@
margin-right: 1rem;
}
}
+
+ &cell-checked {
+ height: 100%;
+
+ &__licenseExpired {
+ color: #f6f6f6;
+ opacity: 0;
+ height: 100%;
+ display: block;
+ }
+ }
}
diff --git a/src/modules/Vocabulary/const.ts b/src/modules/Vocabulary/const.ts
index 9651c0f..0217a8f 100644
--- a/src/modules/Vocabulary/const.ts
+++ b/src/modules/Vocabulary/const.ts
@@ -20,15 +20,16 @@
*
*/
-import keyMirror = require('keymirror');
+import keyMirror = require("keymirror");
const forms = keyMirror({
download: null,
share: null,
- toolbar: null,
+ toolbar: null,
downloadSettings: null,
bundle: null,
notifications: null,
+ requestLinsence: null,
});
const modal = keyMirror({
@@ -46,29 +47,29 @@ const actionTypes = keyMirror({
});
const paths = {
- vocabsList: () => '/vocabulary/list',
- history: () => '/vocabulary/download-history',
+ vocabsList: () => "/vocabulary/list",
+ history: () => "/vocabulary/download-history",
};
const apiPaths = {
- availability: id => `/vocabularies/check/${id}`,
- share: id => `/vocabularies/downloads/${id}/share`,
+ availability: (id) => `/vocabularies/check/${id}`,
+ share: (id) => `/vocabularies/downloads/${id}/share`,
};
const resultsPageSize = 15;
const cdmVersions = [
{
- label: 'CDM VERSION',
- value: '',
+ label: "CDM VERSION",
+ value: "",
},
- {
- label: '4.x',
- value: '4.5',
+ {
+ label: "4.x",
+ value: "4.5",
},
- {
- label: '5.x',
- value: '5',
+ {
+ label: "5.x",
+ value: "5",
},
];
@@ -79,13 +80,9 @@ const bundleStatuses: { [key: string]: string } = keyMirror({
ARCHIVED: null,
});
-export {
- actionTypes,
- apiPaths,
- cdmVersions,
- forms,
- modal,
- paths,
- resultsPageSize,
- bundleStatuses,
+const TYPE_MODAL = {
+ REQUEST_LICENSE: "REQUEST_LICENSE",
+ UPDATE_LICENSE: "UPDATE_LICENSE",
};
+
+export { actionTypes, apiPaths, cdmVersions, forms, modal, paths, resultsPageSize, bundleStatuses, TYPE_MODAL };
| | | |