diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..eefd1082 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,33 @@ +FROM centos:centos7.9.2009 + +# root Installations +RUN yum install -y libpng12 make gcc-c++ sudo +RUN yum install -y https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm +RUN yum install -y git + +# User Creation +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +USER $USERNAME + +# User Installations +RUN touch /home/vscode/.bashrc + +ENV NVM_DIR /home/vscode/.nvm +ENV NODE_VERSION 10.24.1 + +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash \ + && . $NVM_DIR/nvm.sh \ + && nvm install $NODE_VERSION \ + && nvm alias default $NODE_VERSION \ + && nvm use default \ + && npm install -g yarn + +CMD ["/bin/sleep", "infinity"] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..ba0c5621 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,9 @@ +{ + "dockerComposeFile": "docker-compose.yml", + "service": "env", + "remoteUser": "vscode", + "workspaceFolder": "/workspace", + "forwardPorts": [ + 9876 + ] +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..f6efbec1 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3' + +services: + env: + image: johnny94/form-controls-env:v1.0.0 + #build: + # context: . + # dockerfile: Dockerfile + volumes: + - ..:/workspace:cached + - $SSH_AUTH_SOCK:/ssh-agent + environment: + - SSH_AUTH_SOCK=/ssh-agent diff --git a/README.md b/README.md index 1521c455..58916a85 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Form Controls ### Setup Steps 1. Install nvm -2. Install node +2. Install node (Tested version: 10.X.Y) 3. Install yarn - https://yarnpkg.com/en/docs/install ### Build @@ -18,3 +18,9 @@ Form Controls 1. Install dependencies - `yarn` 2. Build - `yarn build` 3. Test - `yarn test` + +Note: OS library libpng12 maybe needs to be installed in order to make dependency installation succeed. + +### Documentation + +https://bahmni.atlassian.net/wiki/spaces/BAH/pages/714276866/Creating+a+Sample+Form-Controls+Property+Component diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..543796e6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,357 @@ +{ + "name": "bahmni-form-controls", + "version": "0.93.11", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "1.1.2", + "@jridgewell/sourcemap-codec": "1.4.14", + "@jridgewell/trace-mapping": "0.3.17" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "0.3.2", + "@jridgewell/trace-mapping": "0.3.17" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "3.1.2", + "tslib": "2.5.0" + } + }, + "clean-css": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "requires": { + "source-map": "0.6.1" + } + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "1.0.0", + "css-what": "6.1.0", + "domhandler": "4.3.1", + "domutils": "2.8.0", + "nth-check": "2.1.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "requires": { + "utila": "0.4.0" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "2.3.0", + "domhandler": "4.3.1", + "entities": "2.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "2.3.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "1.4.1", + "domelementtype": "2.3.0", + "domhandler": "4.3.1" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "requires": { + "no-case": "3.0.4", + "tslib": "2.5.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "requires": { + "camel-case": "4.1.2", + "clean-css": "5.3.2", + "commander": "8.3.0", + "he": "1.2.0", + "param-case": "3.0.4", + "relateurl": "0.2.7", + "terser": "5.16.3" + } + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "requires": { + "@types/html-minifier-terser": "6.1.0", + "html-minifier-terser": "6.1.0", + "lodash": "4.17.21", + "pretty-error": "4.0.0", + "tapable": "2.2.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + } + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "2.3.0", + "domhandler": "4.3.1", + "domutils": "2.8.0", + "entities": "2.2.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "requires": { + "tslib": "2.5.0" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "requires": { + "lower-case": "2.0.2", + "tslib": "2.5.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "1.0.0" + } + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "requires": { + "dot-case": "3.0.4", + "tslib": "2.5.0" + } + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "requires": { + "no-case": "3.0.4", + "tslib": "2.5.0" + } + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "requires": { + "lodash": "4.17.21", + "renderkid": "3.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "requires": { + "css-select": "4.3.0", + "dom-converter": "0.2.0", + "htmlparser2": "6.1.0", + "lodash": "4.17.21", + "strip-ansi": "6.0.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "1.1.2", + "source-map": "0.6.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "5.0.1" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "terser": { + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "requires": { + "@jridgewell/source-map": "0.3.2", + "acorn": "8.8.2", + "commander": "2.20.3", + "source-map-support": "0.5.21" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + } + } +} diff --git a/package.json b/package.json index 4e3b80ab..5c74c76f 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "sinon-as-promised": "^4.0.3", "whatwg-fetch": "^1.0.0" }, - "resolutions": { + "resolutions": { "**/**/lodash": "^4.17.12", "**/**/lodash-es": "^4.17.14", "**/**/mixin-deep": "^1.3.2", diff --git a/src/components/ImageView.jsx b/src/components/ImageView.jsx new file mode 100644 index 00000000..59f7fa82 --- /dev/null +++ b/src/components/ImageView.jsx @@ -0,0 +1,74 @@ +/* eslint-disable react/prefer-stateless-function */ +/* Needs this to attach refs as they cannot be attached to stateless functions. */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ComponentStore from 'src/helpers/componentStore'; +import { IntlShape } from 'react-intl'; + +export class ImageView extends Component { + + _computeImageViewContainerStyle(position) { + + let textAlignPosition; + + switch(position) { + case "center": + textAlignPosition = "center"; + break; + case "right": + textAlignPosition = "right"; + break; + case "left": + default: + textAlignPosition = "left"; + break; + } + + return { + textAlign: textAlignPosition, + padding: '15px', + }; + } + + _computeImageViewStyle(maxHeight, maxWidth) { + + const maxHeightPercentage = isNaN(maxHeight) ? 100 : maxHeight; + const maxWidthPercentage = isNaN(maxWidth) ? 100 : maxWidth; + + return { + maxHeight: maxHeightPercentage + 'vh', + maxWidth: maxWidthPercentage + '%' + }; + } + + render() { + const { intl, enabled, metadata: { label: { value }, properties: { maxHeight, maxWidth, position } } } = this.props; + + const imageUrl = `/bahmni/images/clinical_forms/${value}`; + + const disableClass = enabled ? '' : 'disabled-label'; + return (
+ +
+ ); + } +} + +ImageView.propTypes = { + intl: IntlShape, + metadata: PropTypes.shape({ + type: PropTypes.string.isRequired, + label: PropTypes.object, + translationKey: PropTypes.string, + properties: PropTypes.object, + }), +}; + +ImageView.defaultProps = { +}; + +ComponentStore.registerComponent('imageView', ImageView); +/* eslint-enable react/prefer-stateless-function */ diff --git a/src/components/Link.jsx b/src/components/Link.jsx new file mode 100644 index 00000000..d892f078 --- /dev/null +++ b/src/components/Link.jsx @@ -0,0 +1,41 @@ +/* eslint-disable react/prefer-stateless-function */ +/* Needs this to attach refs as they cannot be attached to stateless functions. */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ComponentStore from 'src/helpers/componentStore'; +import { IntlShape } from 'react-intl'; + +export class Link extends Component { + + render() { + const { intl, enabled, metadata: { label: { value: displayName}, link: { value: url } } } = this.props; + + return ( + + ); + + } +} + +Link.propTypes = { + intl: IntlShape, + metadata: PropTypes.shape({ + type: PropTypes.string.isRequired, + label: PropTypes.object, + link: PropTypes.object, + translationKey: PropTypes.string, + properties: PropTypes.object, + }), +}; + +Link.defaultProps = { +}; + +ComponentStore.registerComponent('link', Link); +/* eslint-enable react/prefer-stateless-function */ diff --git a/src/components/designer/ImageView.jsx b/src/components/designer/ImageView.jsx new file mode 100644 index 00000000..a42f6182 --- /dev/null +++ b/src/components/designer/ImageView.jsx @@ -0,0 +1,166 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ComponentStore from 'src/helpers/componentStore'; +import { SectionMapper } from '../../mapper/SectionMapper'; +import { LabelDesigner } from 'components/designer/Label.jsx'; + +export class ImageViewDesigner extends Component { + + constructor(props) { + super(props); + this.metadata = props.metadata; + this.mapper = new SectionMapper(); + this.storeLabelRef = this.storeLabelRef.bind(this); + this.deleteControl = this.deleteControl.bind(this); + } + + getJsonDefinition() { + const labelJsonDefinition = this.labelControl && this.labelControl.getJsonDefinition(); + return Object.assign({}, this.props.metadata, {}, { label: labelJsonDefinition }); + } + + storeLabelRef(ref) { + this.labelControl = ref; + } + + displayLabel() { + const { metadata: { label, id } } = this.props; + const data = Object.assign({}, label, { id }); + return ( + + ); + } + + deleteControl(event) { + this.props.deleteControl(); + this.props.clearSelectedControl(event); + } + + showDeleteButton() { + if (this.props.showDeleteButton) { + return ( + + ); + } + return null; + } + + stopEventPropagation(event) { + this.props.dispatch(); + event.stopPropagation(); + } + + render() { + const { metadata } = this.props; + return ( +
{ + this.stopEventPropagation(event); + this.props.onSelect(event, metadata); + }} + > + {this.showDeleteButton()} + + + + + +
Filename:{this.displayLabel()}
+
+ ); + } +} + +ImageViewDesigner.propTypes = { + clearSelectedControl: PropTypes.func.isRequired, + deleteControl: PropTypes.func.isRequired, + dispatch: PropTypes.func, + metadata: PropTypes.shape({ + displayType: PropTypes.string, + id: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + label: PropTypes.object, + properties: PropTypes.shape({ + location: PropTypes.shape({ + row: PropTypes.number, + column: PropTypes.number, + }), + }), + type: PropTypes.string.isRequired, + }), + onSelect: PropTypes.func.isRequired, + showDeleteButton: PropTypes.bool, +}; + +const descriptor = { + control: ImageViewDesigner, + designProperties: { + displayName: 'Image View', + isTopLevelComponent: true, + }, + metadata: { + attributes: [ + { + name: 'type', + dataType: 'text', + defaultValue: 'imageView', + }, + { + name: 'value', + dataType: 'text', + defaultValue: 'ImageView', + }, + { + name: 'label', + dataType: 'complex', + attributes: [ + { + name: 'type', + dataType: 'text', + defaultValue: 'label', + }, + { + name: 'value', + dataType: 'text', + defaultValue: 'ImageView', + }, + ], + }, + { + name: 'properties', + dataType: 'complex', + attributes: [ + { + name: 'position', + elementType: 'dropdown', + defaultValue: 'left', + options: [ + 'left', + 'center', + 'right', + ], + }, + { + name: 'maxWidth', + elementType: 'number', + defaultValue: 100, + }, + { + name: 'maxHeight', + elementType: 'number', + defaultValue: 100, + }, + ], + }, + ], + }, +}; + +ComponentStore.registerDesignerComponent('imageView', descriptor); diff --git a/src/components/designer/Link.jsx b/src/components/designer/Link.jsx new file mode 100644 index 00000000..a4c320e5 --- /dev/null +++ b/src/components/designer/Link.jsx @@ -0,0 +1,179 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ComponentStore from 'src/helpers/componentStore'; +import { SectionMapper } from '../../mapper/SectionMapper'; +import { LabelDesigner } from 'components/designer/Label.jsx'; + +export class LinkDesigner extends Component { + + constructor(props) { + super(props); + this.metadata = props.metadata; + this.mapper = new SectionMapper(); + this.storeNameLabelRef = this.storeNameLabelRef.bind(this); + this.storeUrlLabelRef = this.storeUrlLabelRef.bind(this); + this.deleteControl = this.deleteControl.bind(this); + } + + getJsonDefinition() { + const namelabelJsonDefinition = this.nameLabelControl && this.nameLabelControl.getJsonDefinition(); + const urllabelJsonDefinition = this.urlLabelControl && this.urlLabelControl.getJsonDefinition(); + + return Object.assign({}, this.props.metadata, {}, { label: namelabelJsonDefinition, link: urllabelJsonDefinition }); + } + + storeNameLabelRef(ref) { + this.nameLabelControl = ref; + } + + storeUrlLabelRef(ref) { + this.urlLabelControl = ref; + } + + displayNameLabel() { + const { metadata: { label, id } } = this.props; + const data = Object.assign({}, label, { id }); + return ( + + ); + } + + displayUrlLabel() { + const { metadata: { link, id } } = this.props; + const data = Object.assign({}, link, { id }); + return ( + + ); + } + + deleteControl(event) { + this.props.deleteControl(); + this.props.clearSelectedControl(event); + } + + showDeleteButton() { + if (this.props.showDeleteButton) { + return ( + + ); + } + return null; + } + + stopEventPropagation(event) { + this.props.dispatch(); + event.stopPropagation(); + } + + render() { + const { metadata } = this.props; + return ( +
{ + this.stopEventPropagation(event); + this.props.onSelect(event, metadata); + }} + > + {this.showDeleteButton()} + + + + + + + + + + +
+ ); + } +} + +LinkDesigner.propTypes = { + clearSelectedControl: PropTypes.func.isRequired, + deleteControl: PropTypes.func.isRequired, + dispatch: PropTypes.func, + metadata: PropTypes.shape({ + displayType: PropTypes.string, + id: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + label: PropTypes.object, + properties: PropTypes.shape({ + location: PropTypes.shape({ + row: PropTypes.number, + column: PropTypes.number, + }), + }), + type: PropTypes.string.isRequired, + }), + onSelect: PropTypes.func.isRequired, + showDeleteButton: PropTypes.bool, +}; + +const descriptor = { + control: LinkDesigner, + designProperties: { + displayName: 'Link', + isTopLevelComponent: true, + }, + metadata: { + attributes: [ + { + name: 'type', + dataType: 'text', + defaultValue: 'link', + }, + { + name: 'value', + dataType: 'text', + defaultValue: 'link', + }, + { + name: 'label', + dataType: 'complex', + attributes: [ + { + name: 'type', + dataType: 'text', + defaultValue: 'label', + }, + { + name: 'value', + dataType: 'text', + defaultValue: 'name', + }, + ], + }, + { + name: 'link', + dataType: 'complex', + attributes: [ + { + name: 'type', + dataType: 'text', + defaultValue: 'label', + }, + { + name: 'value', + dataType: 'text', + defaultValue: 'url', + }, + ], + }, + ], + }, +}; + +ComponentStore.registerDesignerComponent('link', descriptor); diff --git a/src/components/designer/TableDesigner.jsx b/src/components/designer/TableDesigner.jsx index 5269fefe..f9f26667 100644 --- a/src/components/designer/TableDesigner.jsx +++ b/src/components/designer/TableDesigner.jsx @@ -6,7 +6,7 @@ import { LabelDesigner } from 'components/designer/Label.jsx'; import { GridDesigner } from 'components/designer/Grid.jsx'; import { CellDesigner } from 'components/designer/Cell.jsx'; -const supportedControlTypes = ['obsControl']; +const supportedControlTypes = ['obsControl', 'label', 'imageView', 'link']; const unsupportedProperties = ['addMore']; const NO_OF_TABLE_COLUMNS = 2; diff --git a/src/index.jsx b/src/index.jsx index 3891f1ed..51eae8a9 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -1,6 +1,8 @@ export { Container } from 'components/Container.jsx'; export { ObsControl } from 'components/ObsControl.jsx'; export { Label } from 'components/Label.jsx'; +export { Link } from 'components/Link.jsx'; +export { ImageView } from 'components/ImageView.jsx'; export { TextBox } from 'components/TextBox.jsx'; export { NumericBox } from 'components/NumericBox.jsx'; export { ComplexControl } from 'components/ComplexControl.jsx'; @@ -41,6 +43,8 @@ export { DateDesigner } from 'components/designer/Date.jsx'; export { DateTimeDesigner } from 'components/designer/DateTime.jsx'; export { SectionDesigner } from 'components/designer/Section.jsx'; export { TableDesigner } from 'components/designer/TableDesigner.jsx'; +export { LinkDesigner } from 'components/designer/Link.jsx'; +export { ImageViewDesigner } from 'components/designer/ImageView.jsx'; export { ImageDesigner } from 'components/designer/Image.jsx'; export { VideoDesigner } from 'components/designer/Video.jsx'; export { LocationDesigner } from 'components/designer/Location.jsx'; diff --git a/styles/bahmniAppsFormBuilder/_form.scss b/styles/bahmniAppsFormBuilder/_form.scss index 5e0d6d83..0d367c3e 100644 --- a/styles/bahmniAppsFormBuilder/_form.scss +++ b/styles/bahmniAppsFormBuilder/_form.scss @@ -620,3 +620,27 @@ input.computed-value{ border: 0 !important; pointer-events: none; } + +a.link { + background-color: $bahmniSecondaryColor; + color: white; + box-shadow: 1px 1px 1px #ccc; + border-radius: 10px; + font-size: 20px; + font-family: inherit; + padding: 5px 5px 5px 10px; + font-weight: 800; +} + +.link-container { + width: 100%; + text-align: center; +} + +table.link, table.image-view { + float: left; +} + +table.link td, table.image-view td { + padding: 1px 5px 1px 5px; +}