Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions bundles/framework/myfeatures/MyFeaturesList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Message } from 'oskari-ui';
import { Table, getSorterFor, ToolsContainer } from 'oskari-ui/components/Table';
import { EditOutlined } from '@ant-design/icons';
import { IconButton, DeleteButton } from 'oskari-ui/components/buttons';

const EDIT_ICON_STYLE = {
fontSize: '16px'
};

export const MyFeaturesList = ({ data = [], controller, loading }) => {
const columnSettings = [
{
align: 'left',
title: <Message messageKey='tab.grid.name' />,
dataIndex: 'name',
sorter: getSorterFor('name'),
defaultSortOrder: 'ascend',
render: (title, item) => {
return (
<a onClick={() => controller.openLayer(item.key)}>{title}</a>
);
}
},
{
align: 'left',
title: <Message messageKey='tab.grid.desc' />,
dataIndex: 'desc',
sorter: getSorterFor('description')
},
{
align: 'left',
title: <Message messageKey='tab.grid.source' />,
dataIndex: 'source',
sorter: getSorterFor('source')
},
{
align: 'left',
title: <Message messageKey='tab.grid.createDate' />,
dataIndex: 'created',
sorter: getSorterFor('created'),
width: 135,
render: title => Oskari.util.formatDate(title)
},
{
align: 'left',
title: <Message messageKey='tab.grid.actions' />,
dataIndex: 'key',
width: 100,
render: (title, item) => {
return (
<ToolsContainer>
<IconButton
className='t_edit'
title={<Message messageKey='tab.grid.edit' />}
icon={<EditOutlined style={EDIT_ICON_STYLE} />}
onClick={() => controller.editMyFeatures(item.key)}
/>
<DeleteButton
type='icon'
title={<Message messageKey='tab.confirmDeleteMsg' messageArgs={{ name: item.name }} />}
onConfirm={() => controller.deleteMyFeature(item.key)}
/>
</ToolsContainer>
);
}
}
];

return (
<Table
columns={columnSettings}
dataSource={data.map(item => ({
key: item.getId(),
created: item.getCreated(),
...item.getLocaleValues()
}))}
pagination={false}
loading={loading}
/>
);
};

MyFeaturesList.propTypes = {
data: PropTypes.arrayOf(PropTypes.object),
controller: PropTypes.object.isRequired,
loading: PropTypes.bool
};
23 changes: 23 additions & 0 deletions bundles/framework/myfeatures/MyFeaturesTab.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
import { MyFeaturesList } from './MyFeaturesList';
import { LocaleProvider } from 'oskari-ui/util';

const BUNDLE_KEY = 'MyFeatures';

export const MyFeaturesTab = ({ controller, state }) => {
return (
<LocaleProvider value={{ bundleKey: BUNDLE_KEY }}>
<MyFeaturesList
controller={controller}
data={state.data}
loading={state.loading}
/>
</LocaleProvider>
);
};

MyFeaturesTab.propTypes = {
controller: PropTypes.object.isRequired,
state: PropTypes.object.isRequired
};
22 changes: 22 additions & 0 deletions bundles/framework/myfeatures/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export const BUNDLE_KEY = 'myfeatures';
export const LAYER_TYPE = 'userlayer';
export const MAX_SIZE = 10;

export const TOOL = {
NAME: 'import2',
GROUP: 'myplaces',
ICON: 'upload-material'
};

export const FILE_INPUT_PROPS = {
multiple: false,
allowedTypes: ['application/zip', 'application/octet-stream', 'application/x-zip-compressed', 'multipart/x-zip'],
allowedExtensions: ['zip']
};

export const ERRORS = {
GENERIC: 'generic',
PARSER: 'parser_error',
NO_SRS: 'unknown_projection',
FORMAT: 'format_failure'
};
139 changes: 139 additions & 0 deletions bundles/framework/myfeatures/handler/MyFeaturesHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { StateHandler, controllerMixin } from 'oskari-ui/util';
import { showLayerForm } from '../view/LayerForm';
import { MAX_SIZE, ERRORS } from '../constants';

class MyFeaturesHandler extends StateHandler {
constructor (instance) {
super();
this.instance = instance;
this.sandbox = Oskari.getSandbox();
this.setState({
data: [],
loading: false
});
this.popupControls = null;
this.loc = Oskari.getMsg.bind(null, 'MyFeatures');
this.eventHandlers = this.createEventHandlers();
this.layerMetaType = 'USERLAYER';
this.refreshLayersList();
};

popupCleanup () {
if (this.popupControls) this.popupControls.close();
this.popupControls = null;
}

getName () {
return 'MyFeaturesHandler';
}

showLayerDialog (values) {
const { id } = values;
const isImport = !id;
if (this.popupControls) {
// already opened
if (this.popupControls.id === id) {
this.popupControls.bringToTop();
return;
}
// remove previous popup
this.popupCleanup();
}
const conf = {
maxSize: this.getMaxSize(),
unzippedMaxSize: this.getMaxSize() * 15,
isImport
};
const onSuccess = () => this.popupCleanup();
const onError = (error = ERRORS.GENERIC, values) => {
if (this.popupControls) {
this.popupControls.update(error, values);
}
};
const save = values => {
this.updateState({
loading: true
});
this.instance.getService().submitMyFeatures(values, onSuccess, (err) => onError(err, values));
};
const update = values => {
this.updateState({
loading: true
});
this.instance.getService().updateMyFeatures(id, values, onSuccess, (err) => onError(err, values));
};
const onOk = isImport ? save : update;
this.popupControls = showLayerForm(values, conf, onOk, () => this.popupCleanup());
}

getMaxSize () {
const confMax = this.instance.conf?.maxFileSizeMb;
return isNaN(confMax) ? MAX_SIZE : parseInt(confMax);
}

openLayer (id) {
const addMLrequestBuilder = Oskari.requestBuilder('AddMapLayerRequest');
const addMlRequest = addMLrequestBuilder(id, {
zoomContent: true
});
this.sandbox.request(this.instance, addMlRequest);
}

refreshLayersList () {
this.updateState({
loading: true
});
const layers = this.instance.getMapLayerService().getAllLayersByMetaType(this.layerMetaType);
this.updateState({
data: layers,
loading: false
});
}

editMyFeature (id) {
const layer = this.instance.getMapLayerService().findMapLayer(id);
const values = {
locale: layer.getLocale(),
style: layer.getCurrentStyle().getFeatureStyle(),
id
};
this.showLayerDialog(values);
}

deleteMyFeature (id) {
this.updateState({
loading: true
});
this.instance.getService().deleteMyFeature(id);
}

createEventHandlers () {
const handlers = {
MapLayerEvent: (event) => {
const operation = event.getOperation();
if (operation === 'add' || operation === 'update' || operation === 'remove') {
this.refreshLayersList();
}
}
};
Object.getOwnPropertyNames(handlers).forEach(p => this.sandbox.registerForEventByName(this, p));
return handlers;
}

onEvent (e) {
const handler = this.eventHandlers[e.getName()];
if (!handler) {
return;
}

return handler.apply(this, [e]);
}
}

const wrapped = controllerMixin(MyFeaturesHandler, [
'editMyFeature',
'deleteMyFeature',
'openLayer'
]);

export { wrapped as MyFeaturesHandler };
4 changes: 4 additions & 0 deletions bundles/framework/myfeatures/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import './instance';

// register create function for bundleid
Oskari.bundle('myfeatures', () => Oskari.clazz.create('Oskari.mapframework.bundle.myfeatures.MyFeaturesBundleInstance'));
Loading