mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-16 06:23:18 +00:00
incorporate phraseanet-production-client into phraseanet
This commit is contained in:
19
Phraseanet-production-client/.babelrc
Normal file
19
Phraseanet-production-client/.babelrc
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
|
||||
"ignore": [
|
||||
"foo.js",
|
||||
"bar/**/*.js"
|
||||
],
|
||||
"presets": [
|
||||
"es2015", "stage-0"
|
||||
],
|
||||
"env": {
|
||||
"start": {
|
||||
/* TODO: */
|
||||
/* fill with hmr settings when there is a new release */
|
||||
/* to play nice with babel 6*/
|
||||
}
|
||||
},
|
||||
/* Add plugins here**/
|
||||
"plugins": ["babel-plugin-syntax-jsx"]
|
||||
}
|
30
Phraseanet-production-client/.editorconfig
Normal file
30
Phraseanet-production-client/.editorconfig
Normal file
@@ -0,0 +1,30 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
# A special property that should be specified at the top of the file outside of
|
||||
# any sections. Set to true to stop .editor config file search on current file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
# Indentation style
|
||||
# Possible values - tab, space
|
||||
indent_style = space
|
||||
|
||||
# Indentation size in single-spaced characters
|
||||
# Possible values - an integer, tab
|
||||
indent_size = 4
|
||||
|
||||
# Line ending file format
|
||||
# Possible values - lf, crlf, cr
|
||||
end_of_line = lf
|
||||
|
||||
# File character encoding
|
||||
# Possible values - latin1, utf-8, utf-16be, utf-16le
|
||||
charset = utf-8
|
||||
|
||||
# Denotes whether to trim whitespace at the end of lines
|
||||
# Possible values - true, false
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# Denotes whether file should end with a newline
|
||||
# Possible values - true, false
|
||||
insert_final_newline = true
|
3
Phraseanet-production-client/.env
Normal file
3
Phraseanet-production-client/.env
Normal file
@@ -0,0 +1,3 @@
|
||||
NODE_PATH=./src
|
||||
NODE_ENV=development
|
||||
PORT=80
|
4
Phraseanet-production-client/.eslintignore
Normal file
4
Phraseanet-production-client/.eslintignore
Normal file
@@ -0,0 +1,4 @@
|
||||
dist/*
|
||||
node_modules/*
|
||||
**/node_modules/*
|
||||
config/**
|
186
Phraseanet-production-client/.eslintrc
Normal file
186
Phraseanet-production-client/.eslintrc
Normal file
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "babel-eslint",
|
||||
"globals": {
|
||||
"document": true,
|
||||
"window": true,
|
||||
"spy",
|
||||
"mocha",
|
||||
"stub",
|
||||
"beforeEach",
|
||||
"useFakeTimers": true,
|
||||
"useFakeXMLHttpRequest": true,
|
||||
"useFakeServer": true
|
||||
},
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"modules": true,
|
||||
"es6": true
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true,
|
||||
"node": true
|
||||
|
||||
},
|
||||
"rules": {
|
||||
// /* airbnb javascript style guide rules */
|
||||
// "strict": [2, "never"],
|
||||
// // es6
|
||||
// //"no-var": 2,
|
||||
// // variables
|
||||
//"no-shadow": 2,
|
||||
"no-shadow-restricted-names": 2,
|
||||
// "no-unused-vars": [2, {
|
||||
// "vars": "all",
|
||||
// "args": "none"
|
||||
// }],
|
||||
"no-undef": 2,
|
||||
// "no-use-before-define": [2, "nofunc"],
|
||||
// possible errors
|
||||
"comma-dangle": 0,
|
||||
//"no-cond-assign": [2, "always"],
|
||||
"no-debugger": 1,
|
||||
//"no-alert": 1,
|
||||
"no-constant-condition": 1,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
//"no-empty": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extra-boolean-cast": 0,
|
||||
"no-extra-semi": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-inner-declarations": 2,
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-unreachable": 2,
|
||||
"use-isnan": 2,
|
||||
"block-scoped-var": 2,
|
||||
// best practices
|
||||
//"consistent-return": 2,
|
||||
"curly": [2, "multi-line"],
|
||||
"default-case": 2,
|
||||
"dot-notation": [2, {
|
||||
"allowKeywords": true
|
||||
}],
|
||||
"eqeqeq": 2,
|
||||
//"guard-for-in": 2,
|
||||
"no-caller": 2,
|
||||
"no-eq-null": 2,
|
||||
"no-eval": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-fallthrough": 0,
|
||||
"no-floating-decimal": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-lone-blocks": 2,
|
||||
//"no-loop-func": 2,
|
||||
//"no-multi-str": 2,
|
||||
"no-native-reassign": 2,
|
||||
//"no-new": 2,
|
||||
"no-new-func": 2,
|
||||
// "no-new-wrappers": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
// "no-param-reassign": [2, {
|
||||
// "props": false
|
||||
// }],
|
||||
"no-proto": 2,
|
||||
"no-redeclare": 2,
|
||||
"no-return-assign": 2,
|
||||
"no-script-url": 2,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
//"no-throw-literal": 2,
|
||||
"no-with": 2,
|
||||
"radix": 2,
|
||||
// "vars-on-top": 2,
|
||||
//"wrap-iife": [2, "any"],
|
||||
"yoda": 2,
|
||||
// style
|
||||
"indent": [0, 0],
|
||||
"brace-style": [2,
|
||||
"1tbs", {
|
||||
"allowSingleLine": true
|
||||
}
|
||||
],
|
||||
"quotes": [
|
||||
2, "single", "avoid-escape"
|
||||
],
|
||||
// "camelcase": [2, {
|
||||
// "properties": "never"
|
||||
// }],
|
||||
"comma-spacing": [2, {
|
||||
"before": false,
|
||||
"after": true
|
||||
}],
|
||||
"comma-style": [2, "last"],
|
||||
"eol-last": 2,
|
||||
"key-spacing": [2, {
|
||||
"beforeColon": false,
|
||||
"afterColon": true
|
||||
}],
|
||||
// "new-cap": [2, {
|
||||
// "newIsCap": true
|
||||
// }],
|
||||
"no-multiple-empty-lines": [2, {
|
||||
"max": 2
|
||||
}],
|
||||
//"no-nested-ternary": 2,
|
||||
"no-new-object": 2,
|
||||
"no-spaced-func": 2,
|
||||
"no-trailing-spaces": 0,
|
||||
//"no-extra-parens": 2,
|
||||
"no-underscore-dangle": 0,
|
||||
"one-var": [2, "never"],
|
||||
"padded-blocks": 0,
|
||||
"semi-spacing": [2, {
|
||||
"before": false,
|
||||
"after": true
|
||||
}],
|
||||
"keyword-spacing": 2,
|
||||
"space-before-blocks": 2,
|
||||
"space-infix-ops": 2,
|
||||
//"spaced-comment": 2,
|
||||
|
||||
/* custom rules */
|
||||
"no-console": 0,
|
||||
"space-before-function-paren": [2, {
|
||||
"named": "never",
|
||||
"anonymous": "always"
|
||||
}],
|
||||
"func-names": 0,
|
||||
//"consistent-this": [2, "this"],
|
||||
"func-style": [0, "expression"],
|
||||
//"max-nested-callbacks": [2, 3],
|
||||
"new-parens": 2,
|
||||
"no-array-constructor": 2,
|
||||
"no-else-return": 0,
|
||||
//"no-inline-comments": 2,
|
||||
// "no-lonely-if": 2,
|
||||
"no-mixed-spaces-and-tabs": 1,
|
||||
"operator-assignment": 0,
|
||||
"quote-props": [2, "as-needed"],
|
||||
"sort-vars": [0, {
|
||||
"ignoreCase": true
|
||||
}],
|
||||
"space-in-brackets": [0, "never", {
|
||||
"arraysInArrays": false,
|
||||
"arraysInObjects": false,
|
||||
"singleValue": false,
|
||||
"objectsInArrays": false,
|
||||
"objectsInObjects": false,
|
||||
"propertyName": false
|
||||
}],
|
||||
"space-in-parens": [2, "never"],
|
||||
"space-unary-ops": [2, {
|
||||
"words": true,
|
||||
"nonwords": false
|
||||
}],
|
||||
"wrap-regex": 1
|
||||
},
|
||||
plugins: []
|
||||
}
|
8
Phraseanet-production-client/.gitignore
vendored
Normal file
8
Phraseanet-production-client/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
*.log
|
||||
node_modules
|
||||
coverage
|
||||
npm-debug.log
|
||||
.DS_Store
|
||||
dist
|
||||
bower_components
|
||||
.idea
|
1
Phraseanet-production-client/.npmignore
Normal file
1
Phraseanet-production-client/.npmignore
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
26
Phraseanet-production-client/.travis.yml
Normal file
26
Phraseanet-production-client/.travis.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- '13.13.0'
|
||||
|
||||
# Use container-based Travis infrastructure.
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
before_install:
|
||||
- nvm install stable
|
||||
|
||||
notifications:
|
||||
email: true
|
||||
branches:
|
||||
except:
|
||||
- "/^v\\d+\\.\\d+\\.\\d+$/"
|
||||
|
||||
after_script:
|
||||
- npm run coveralls
|
||||
|
||||
# Upload to coveralls, but don't _fail_ if coveralls is down.
|
||||
- cat coverage/lcov.info | node_modules/.bin/coveralls || echo "Coveralls upload failed"
|
5
Phraseanet-production-client/CHANGELOG.md
Normal file
5
Phraseanet-production-client/CHANGELOG.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## 0.1.0
|
||||
|
||||
- initial release
|
19
Phraseanet-production-client/LICENSE.md
Normal file
19
Phraseanet-production-client/LICENSE.md
Normal file
@@ -0,0 +1,19 @@
|
||||
##The MIT License (MIT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
15
Phraseanet-production-client/PULL_REQUEST_TEMPLATE.md
Normal file
15
Phraseanet-production-client/PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## Changelog
|
||||
### Changed
|
||||
- Breaking change
|
||||
|
||||
### Fixes
|
||||
- PHRAS-XXX: Short description of bug and fix
|
||||
- Short description of bug and fix without issue/ticket
|
||||
|
||||
### Adds
|
||||
- PHRAS-XXX: Short feature description
|
||||
- Short feature description without issue/ticket
|
||||
|
||||
### Removes
|
||||
- PHRAS-XXX: Short feature removal description
|
||||
- Short feature removal description without issue/ticket
|
49
Phraseanet-production-client/README.md
Normal file
49
Phraseanet-production-client/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Phraseanet Production Client
|
||||
[](https://travis-ci.org/alchemy-fr/Phraseanet-production-client)
|
||||
[](https://david-dm.org/alchemy-fr/Phraseanet-production-client#info=devDependencies)
|
||||
[](https://david-dm.org/alchemy-fr/Phraseanet-production-client)
|
||||
[](https://coveralls.io/github/alchemy-fr/Phraseanet-production-client?branch=master)
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
Node `^5.0.0`.
|
||||
|
||||
## Dev workflow
|
||||
|
||||
- Go to Phraseanet-production-client-folder
|
||||
- make your modification
|
||||
- Generate dist ```npm run dist```
|
||||
- ```make install_asset``` to copy assets in www/assets folder
|
||||
- If features is finished ```dist``` folder is to be commited
|
||||
|
||||
## Available commands
|
||||
|
||||
* `npm run production` - Build task that generate a minified script for production
|
||||
* `npm run clean` - Remove the `dist` folder and it's files
|
||||
* `npm run eslint:source` - Lint the source
|
||||
* `npm run eslint:common` - Lint the unit tests shared by Karma and Mocha
|
||||
* `npm run eslint:server` - Lint the unit tests for server
|
||||
* `npm run eslint:browser` - Lint the unit tests for browser
|
||||
* `npm run eslint:fix` - ESLint will try to fix as many issues as possible in your source files
|
||||
* `npm run clean` - Remove the coverage report and the *dist* folder
|
||||
* `npm run test` - Runs unit tests for both server and the browser
|
||||
* `npm run test:browser` - Runs the unit tests for browser / client
|
||||
* `npm run test:server` - Runs the unit tests on the server
|
||||
* `npm run watch:server` - Run all unit tests for server & watch files for changes
|
||||
* `npm run watch:browser` - Run all unit tests for browser & watch files for changes
|
||||
* `npm run karma:firefox` - Run all unit tests with Karma & Firefox
|
||||
* `npm run karma:chrome` - Run all unit tests with Karma & Chrome
|
||||
* `npm run karma:ie` - Run all unit tests with Karma & Internet Explorer
|
||||
* `npm run packages` - List installed packages
|
||||
* `npm run package:purge` - Remove all dependencies
|
||||
* `npm run package:reinstall` - Reinstall all dependencies
|
||||
* `npm run package:check` - shows a list over dependencies with a higher version number then the current one - if any
|
||||
* `npm run package:upgrade` - Automaticly upgrade all devDependencies & dependencies, and update package.json
|
||||
* `npm run package:dev` - Automaticly upgrade all devDependencies and update package.json
|
||||
* `npm run package:prod` - Automaticly upgrade all dependencies and update package.json
|
||||
* `npm run asset-server` - starts a asset server with hot module replacement (WDS) on port 8080
|
||||
|
||||
## Credits
|
||||
|
||||
based on [Trolly](https://github.com/Kflash/trolly) an es6 boilerplate by [KFlash](https://github.com/kflash)
|
6
Phraseanet-production-client/config/banner.js
Normal file
6
Phraseanet-production-client/config/banner.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import pkg from '../package.json';
|
||||
|
||||
export default [
|
||||
pkg.name + '',
|
||||
' version ' + pkg.version
|
||||
];
|
15
Phraseanet-production-client/config/config.js
Normal file
15
Phraseanet-production-client/config/config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const _root = __dirname + '/../';
|
||||
|
||||
module.exports = {
|
||||
|
||||
// path helpers
|
||||
_app: 'app',
|
||||
minified: 'app.min.js',
|
||||
dev: 'app.js',
|
||||
eslintDir: _root + '.eslintrc',
|
||||
distDir: _root + 'dist',
|
||||
sourceDir: _root + 'src/',
|
||||
testDir: _root + 'tests',
|
||||
setupDir: _root + 'tests/setup/node.js',
|
||||
karmaConf: _root + 'config/karma.conf.js'
|
||||
};
|
45
Phraseanet-production-client/config/environment.js
Normal file
45
Phraseanet-production-client/config/environment.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/* eslint-disable */
|
||||
import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
import {
|
||||
defaults
|
||||
}
|
||||
from 'lodash';
|
||||
|
||||
dotenv.load({
|
||||
silent: false,
|
||||
path: path.resolve(__dirname, '../.env')
|
||||
});
|
||||
|
||||
const {
|
||||
ENVIRONMENT,
|
||||
HOT_RELOAD,
|
||||
NODE_ENV,
|
||||
HOST,
|
||||
PORT,
|
||||
WEBPACK_DEV_SERVER_PORT
|
||||
} = defaults(process.env, {
|
||||
ENVIRONMENT: 'development',
|
||||
// localhost
|
||||
HOST: 'localhost',
|
||||
// port to use with the asset server
|
||||
PORT: '8000'
|
||||
}),
|
||||
IS_PROD = () => {
|
||||
return ( NODE_ENV === 'production' || ENVIRONMENT === 'prod' || ENVIRONMENT === 'production' );
|
||||
},
|
||||
IS_DEV = !IS_PROD,
|
||||
ENVIRONMENT_NAME = IS_PROD ? 'production' : 'development';
|
||||
|
||||
process.env.NODE_ENV = IS_PROD ? 'production' : 'development';
|
||||
|
||||
export default {
|
||||
IS_PROD,
|
||||
IS_DEV,
|
||||
ENVIRONMENT_NAME,
|
||||
HOST,
|
||||
PORT,
|
||||
WEBPACK_DEV_SERVER_PORT,
|
||||
HOT_RELOAD
|
||||
};
|
||||
/* eslint-enable */
|
102
Phraseanet-production-client/config/karma.conf.js
Normal file
102
Phraseanet-production-client/config/karma.conf.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import webpackConfig from './webpack/webpack.karma.config';
|
||||
|
||||
// Karma configuration here
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
// list of files to exclude
|
||||
exclude: [],
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'./node_modules/jquery/dist/jquery.js',
|
||||
'./node_modules/babel-polyfill/dist/polyfill.js',
|
||||
'./node_modules/phantomjs-polyfill/bind-polyfill.js',
|
||||
'./test/**/*.browser.js'
|
||||
],
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: [
|
||||
'sinon-chai',
|
||||
'sinon',
|
||||
'chai',
|
||||
'mocha'
|
||||
], //use mocha and sinon-chai as framework
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
// 'src/**/*.js': ['coverage'],
|
||||
'test/**/*.browser.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
// test results reporter to use
|
||||
reporters: ['progress', 'mocha','coverage'],
|
||||
coverageReporter: {
|
||||
reporters: [{
|
||||
type: 'text'
|
||||
}, {
|
||||
type: 'lcovonly',
|
||||
subdir: '.'
|
||||
}, {
|
||||
type: 'html',
|
||||
dir: 'coverage/'
|
||||
}
|
||||
]
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
noInfo: true
|
||||
},
|
||||
plugins: [
|
||||
'karma-sinon-chai',
|
||||
'karma-sinon',
|
||||
'karma-chai',
|
||||
'karma-webpack',
|
||||
'karma-mocha',
|
||||
'karma-mocha-reporter',
|
||||
'karma-phantomjs-launcher',
|
||||
'karma-chrome-launcher',
|
||||
'karma-firefox-launcher',
|
||||
'karma-ie-launcher',
|
||||
'karma-coverage',
|
||||
'karma-sourcemap-loader'
|
||||
],
|
||||
// Start these browsers, currently available:
|
||||
// - Chrome
|
||||
// - ChromeCanary
|
||||
// - Firefox
|
||||
// - Opera (has to be installed with `npm install karma-opera-launcher`)
|
||||
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
|
||||
browsers: ['PhantomJS'],
|
||||
browserDisconnectTimeout: 10000,
|
||||
browserDisconnectTolerance: 2,
|
||||
// concurrency level how many browser should be started simultaneously
|
||||
concurrency: 4,
|
||||
// If browser does not capture in given timeout [ms], kill it
|
||||
captureTimeout: 100000,
|
||||
browserNoActivityTimeout: 30000,
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: true,
|
||||
});
|
||||
|
||||
if (process.env.TRAVIS) {
|
||||
|
||||
config.logLevel = config.LOG_DEBUG;
|
||||
// Karma (with socket.io 1.x) buffers by 50 and 50 tests can take a long time on IEs;-)
|
||||
config.browserNoActivityTimeout = 120000;
|
||||
|
||||
// Debug logging into a file, that we print out at the end of the build.
|
||||
config.loggers.push({
|
||||
type: 'file',
|
||||
filename: 'logs/karma.log'
|
||||
});
|
||||
}
|
||||
};
|
15
Phraseanet-production-client/config/mocha.conf.js
Normal file
15
Phraseanet-production-client/config/mocha.conf.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-disable */
|
||||
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
global.babel = require('babel-core/register');
|
||||
global.chai = require("chai");
|
||||
// global.$ = require("jquery");
|
||||
global.chaiAsPromised = require("chai-as-promised");
|
||||
global.chai.use(chaiAsPromised);
|
||||
global.expect = global.chai.expect;
|
||||
global.sinon = require('sinon');
|
||||
global.BROWSER = false;
|
||||
|
||||
|
||||
|
9
Phraseanet-production-client/config/mocha.opts
Normal file
9
Phraseanet-production-client/config/mocha.opts
Normal file
@@ -0,0 +1,9 @@
|
||||
./test/**/*.spec.js
|
||||
|
||||
--require ./config/mocha.conf.js
|
||||
--reporter spec
|
||||
--ui bdd
|
||||
--compilers js:babel-core/register
|
||||
--recursive
|
||||
--timeout 15000
|
||||
--bail
|
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* WEBPACK CONFIG
|
||||
*
|
||||
*/
|
||||
/* eslint-disable no-var */
|
||||
require('babel-core/register');
|
||||
|
||||
// Webpack config for development
|
||||
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const pkg = require('../../package.json');
|
||||
// const banner = require('../banner');
|
||||
const WebpackNotifierPlugin = require('webpack-notifier');
|
||||
const config = require('../config');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
// add loader for external stylesheets:
|
||||
var extractCSS = new ExtractTextPlugin({
|
||||
filename: '[name].css',
|
||||
allChunks: true
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
// entry points
|
||||
entry: {
|
||||
production: config.sourceDir + 'prod/index.js',
|
||||
lightbox: config.sourceDir + 'lightbox/index.js',
|
||||
'lightbox-mobile': config.sourceDir + 'lightbox-mobile/index.js',
|
||||
permaview: config.sourceDir + 'permaview/index.js',
|
||||
authenticate: [config.sourceDir + 'authenticate/index.js'],
|
||||
account: [config.sourceDir + 'account/index.js'],
|
||||
'skin-000000': [config.sourceDir + 'skins/skin-000000.js'],
|
||||
'skin-959595': [config.sourceDir + 'skins/skin-959595.js'],
|
||||
'skin-FFFFFF': [config.sourceDir + 'skins/skin-FFFFFF.js']
|
||||
},
|
||||
cache: true,
|
||||
watch: true,
|
||||
devtool: 'inline-source-map',
|
||||
output: {
|
||||
path: config.distDir,
|
||||
filename: '[name].js',
|
||||
chunkFilename: 'lazy-[name].js',
|
||||
libraryTarget: 'umd',
|
||||
library: config._app,
|
||||
publicPath: '/assets/production/'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
enforce: 'pre',
|
||||
loader: 'eslint-loader',
|
||||
exclude: /node_modules/,
|
||||
include: path.join(__dirname, '../../src')
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
loader: 'babel-loader',
|
||||
options: { presets: ['es2015', 'stage-0'] },
|
||||
}],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|svg|png|jpg|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: '[name].[hash:6].[ext]',
|
||||
}
|
||||
}
|
||||
],
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|svg|png|jpg|jpeg|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[hash:6].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
"style-loader",
|
||||
"css-loader"
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /videojs-flash\.js$/,
|
||||
loader: 'script-loader'
|
||||
},
|
||||
// exclude skins as inline-css in dev env
|
||||
// {
|
||||
// test: /\.scss$/,
|
||||
// exclude: /src\/skins\//,
|
||||
// loaders: ['style', 'css', 'resolve-url', 'sass?sourceMap']
|
||||
// },
|
||||
// only skins are extracted as external file in dev env:
|
||||
// every css should be exported as file in dev env
|
||||
{
|
||||
test: /\.scss$/,
|
||||
// exclude: /src\/(?!skins)/,
|
||||
// include: [path.join(__dirname, '../../src'), path.join(__dirname, '../../stylesheets')],
|
||||
use: ExtractTextPlugin.extract({
|
||||
fallback: "style-loader",
|
||||
use: [
|
||||
'css-loader',
|
||||
'resolve-url-loader',
|
||||
{ loader: 'sass-loader', options: { sourceMap: true } }
|
||||
],
|
||||
publicPath: './'
|
||||
})
|
||||
},{
|
||||
test: require.resolve('jquery-lazyload'),
|
||||
use: "imports-loader?this=>window"
|
||||
}, {
|
||||
test: require.resolve('geonames-server-jquery-plugin/jquery.geonames'),
|
||||
use: "imports-loader?this=>window"
|
||||
}, {
|
||||
test: require.resolve('bootstrap-multiselect'),
|
||||
use: "imports-loader?this=>window"
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['*', '.js', '.css', '.scss']
|
||||
},
|
||||
plugins: [
|
||||
new WebpackNotifierPlugin({
|
||||
alwaysNotify: true
|
||||
}),
|
||||
// new webpack.BannerPlugin(banner),
|
||||
new webpack.ProvidePlugin({
|
||||
"videojs": "video.js",
|
||||
"window.videojs": "video.js"
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'__DEV__': true,
|
||||
'process.env.NODE_ENV': JSON.stringify('development'),
|
||||
VERSION: JSON.stringify(pkg.version)
|
||||
}),
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'commons',
|
||||
chunks: ['production', 'lightbox'],
|
||||
minChunks: 2
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
debug: true,
|
||||
options: {
|
||||
eslint: {
|
||||
configFile: config.eslintDir
|
||||
}
|
||||
}
|
||||
}),
|
||||
extractCSS
|
||||
// i18next
|
||||
],
|
||||
externals: {
|
||||
jquery: 'jQuery',
|
||||
ui: 'jQuery.ui'
|
||||
}
|
||||
};
|
@@ -0,0 +1,37 @@
|
||||
/* eslint-disable no-var, strict */
|
||||
require('babel-core/register');
|
||||
|
||||
const webpack = require('webpack');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const environment = require('../environment');
|
||||
const config = require('./webpack.development.config');
|
||||
|
||||
config.devServer = {
|
||||
hot: true
|
||||
}
|
||||
config.plugins = [
|
||||
// Used for hot-reload
|
||||
new webpack.HotModuleReplacementPlugin()
|
||||
];
|
||||
|
||||
new WebpackDevServer(webpack(config), {
|
||||
publicPath: 'http://localhost:8080/assets/',
|
||||
// Configure hot replacement
|
||||
// The rest is terminal configurations
|
||||
quiet: false,
|
||||
noInfo: true,
|
||||
historyApiFallback: {
|
||||
index: './templates/index.html'
|
||||
},
|
||||
stats: {
|
||||
colors: true
|
||||
}
|
||||
// We fire up the development server and give notice in the terminal
|
||||
// that we are starting the initial bundle
|
||||
}).listen(8080, environment.HOST, function(err, result) {
|
||||
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
console.log('The asset server is listening at localhost: 8080');
|
||||
});
|
@@ -0,0 +1,100 @@
|
||||
// Webpack config for development
|
||||
import webpack from 'webpack';
|
||||
import path from 'path';
|
||||
import config from '../config';
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
// add loader for external stylesheets:
|
||||
var extractCSS = new ExtractTextPlugin({
|
||||
filename: '[name].css',
|
||||
allChunks: true
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
cache: true,
|
||||
devtool: 'inline-source-map',
|
||||
output: {},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
enforce: 'post',
|
||||
include: path.resolve('src/'),
|
||||
use: 'istanbul-instrumenter-loader'
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
'css-loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
// exclude: /src\/(?!skins)/,
|
||||
// include: [path.join(__dirname, '../../src'), path.join(__dirname, '../../stylesheets')],
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: [
|
||||
'css-loader',
|
||||
'resolve-url-loader',
|
||||
{ loader: 'sass-loader', options: { sourceMap: true } }
|
||||
],
|
||||
publicPath: './'
|
||||
})
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|svg|png|jpg|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: '[name].[hash:6].[ext]',
|
||||
}
|
||||
}
|
||||
],
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|svg|png|jpg|jpeg|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[hash:6].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
loader: 'babel-loader',
|
||||
options: { presets: ['es2015', 'stage-0'] },
|
||||
}],
|
||||
},
|
||||
{
|
||||
test: require.resolve('jquery-lazyload'),
|
||||
use: "imports-loader?this=>window"
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['*', '.js', '.css']
|
||||
},
|
||||
externals: {
|
||||
jquery: 'jQuery',
|
||||
ui: 'jQuery.ui'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.NormalModuleReplacementPlugin(/\.css$/, path.resolve('./src', './empty.js')),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
debug: true
|
||||
}),
|
||||
extractCSS
|
||||
],
|
||||
devServer: {
|
||||
hot: true
|
||||
}
|
||||
};
|
@@ -0,0 +1,131 @@
|
||||
require('babel-core/register');
|
||||
// Webpack config for creating the production bundle.
|
||||
|
||||
const webpack = require('webpack');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const path = require('path');
|
||||
const WebpackNotifierPlugin = require('webpack-notifier');
|
||||
const PKG_LOCATION = require(path.join(__dirname, '../../package.json'));
|
||||
const config = require('../config');
|
||||
const webpackConfig = require('./webpack.development.config');
|
||||
// add loader for external stylesheets:
|
||||
var extractCSS = new ExtractTextPlugin({
|
||||
filename: '[name].css',
|
||||
allChunks: true
|
||||
});
|
||||
|
||||
module.exports = Object.assign({}, webpackConfig, {
|
||||
|
||||
cache: false,
|
||||
devtool: false,
|
||||
watch: false,
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
loader: 'babel-loader',
|
||||
options: { presets: ['es2015', 'stage-0'] },
|
||||
}],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|svg|png|jpg|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: '[name].[hash:6].[ext]',
|
||||
}
|
||||
}
|
||||
],
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|svg|png|jpg|jpeg|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[hash:6].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
"style-loader",
|
||||
"css-loader"
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /videojs-flash\.js$/,
|
||||
loader: 'script-loader'
|
||||
},
|
||||
// exclude skins as inline-css in dev env
|
||||
// {
|
||||
// test: /\.scss$/,
|
||||
// exclude: /src\/skins\//,
|
||||
// loaders: ['style', 'css', 'resolve-url', 'sass']
|
||||
// },
|
||||
// only skins are extracted as external file in dev env:
|
||||
{
|
||||
test: /\.scss$/,
|
||||
// exclude: /src\/(?!skins)/,
|
||||
// include: [path.join(__dirname, '../../src'), path.join(__dirname, '../../stylesheets')],
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: [
|
||||
'css-loader',
|
||||
'resolve-url-loader',
|
||||
{ loader: 'sass-loader', options: { sourceMap: true } }
|
||||
],
|
||||
publicPath: './'
|
||||
})
|
||||
},
|
||||
{
|
||||
test: require.resolve('jquery-lazyload'),
|
||||
use: "imports-loader?this=>window"
|
||||
}, {
|
||||
test: require.resolve('geonames-server-jquery-plugin/jquery.geonames'),
|
||||
use: "imports-loader?this=>window"
|
||||
}, {
|
||||
test: require.resolve('bootstrap-multiselect'),
|
||||
use: "imports-loader?this=>window"
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
$: "jquery",
|
||||
jQuery: "jquery",
|
||||
"videojs": "video.js",
|
||||
"window.videojs": "video.js"
|
||||
}),
|
||||
// Notifier
|
||||
new WebpackNotifierPlugin({
|
||||
title: PKG_LOCATION.name,
|
||||
alwaysNotify: true
|
||||
}),
|
||||
// optimizations
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'__DEV__': false,
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
VERSION: JSON.stringify(PKG_LOCATION.version)
|
||||
}),
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'commons',
|
||||
chunks: ['production', 'lightbox'],
|
||||
minChunks: 2
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
debug: true
|
||||
}),
|
||||
extractCSS
|
||||
],
|
||||
devServer: {
|
||||
hot: true
|
||||
}
|
||||
});
|
@@ -0,0 +1,58 @@
|
||||
require('babel-core/register');
|
||||
|
||||
// Webpack config for creating the minified production bundle.
|
||||
|
||||
const webpack = require('webpack');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const path = require('path');
|
||||
const WebpackNotifierPlugin = require('webpack-notifier');
|
||||
const PKG_LOCATION = require(path.join(__dirname, '../../package.json'));
|
||||
const config = require('../config');
|
||||
const webpackConfig = require('./webpack.production.config')
|
||||
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
|
||||
var extractCSS = new ExtractTextPlugin({
|
||||
filename: '[name].min.css',
|
||||
allChunks: true
|
||||
});
|
||||
|
||||
module.exports = Object.assign({}, webpackConfig, {
|
||||
output: {
|
||||
path: config.distDir,
|
||||
filename: '[name].min.js',
|
||||
chunkFilename: 'lazy-[name].min.js',
|
||||
libraryTarget: 'umd',
|
||||
library: config._app,
|
||||
publicPath: '/assets/production/'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
$: "jquery",
|
||||
jQuery: "jquery",
|
||||
"videojs": "video.js",
|
||||
"window.videojs": "video.js"
|
||||
}),
|
||||
// Notifier
|
||||
new WebpackNotifierPlugin({
|
||||
title: PKG_LOCATION.name,
|
||||
alwaysNotify: true
|
||||
}),
|
||||
// optimizations
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'__DEV__': false,
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
VERSION: JSON.stringify(PKG_LOCATION.version)
|
||||
}),
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'commons',
|
||||
chunks: ['production', 'lightbox'],
|
||||
minChunks: 2
|
||||
}),
|
||||
extractCSS,
|
||||
new OptimizeCssAssetsPlugin({
|
||||
assetNameRegExp: /\.min\.css$/,
|
||||
cssProcessorOptions: { discardComments: { removeAll: true }, zindex: false }
|
||||
})
|
||||
]
|
||||
});
|
2
Phraseanet-production-client/karma.conf.js
Normal file
2
Phraseanet-production-client/karma.conf.js
Normal file
@@ -0,0 +1,2 @@
|
||||
require('babel-core/register');
|
||||
module.exports = require('./config/karma.conf');
|
2
Phraseanet-production-client/logs/.gitignore
vendored
Normal file
2
Phraseanet-production-client/logs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
19053
Phraseanet-production-client/package-lock.json
generated
Normal file
19053
Phraseanet-production-client/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
168
Phraseanet-production-client/package.json
Normal file
168
Phraseanet-production-client/package.json
Normal file
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"name": "phraseanet-production-client",
|
||||
"version": "0.34.272-d",
|
||||
"description": "Phraseanet frontend dependencies",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"dev": "npm run clean && set NODE_ENV=devlopment && npx webpack --config ./config/webpack/webpack.development.config.js --progress --profile --colors",
|
||||
"production": "npm run clean && set NODE_ENV=production && npx webpack --config ./config/webpack/webpack.production.config.js --progress --profile --colors",
|
||||
"dist": "npm run clean && set NODE_ENV=production && npx webpack --config ./config/webpack/webpack.production.config.js --progress --profile --colors && npx webpack --config ./config/webpack/webpack.production.minified.config.js --progress --profile --colors",
|
||||
"test": "npm run test:browser",
|
||||
"test:server": "mocha --opts config/mocha.opts",
|
||||
"test:browser": "./node_modules/.bin/karma start --single-run",
|
||||
"watch:server": "npm run test:server -- --watch",
|
||||
"watch:browser": "./node_modules/.bin/karma start --auto-watch --no-single-run",
|
||||
"eslint:source": "eslint ./src/**/*.js",
|
||||
"eslint:fix": "eslint --fix ./src/**/*.js",
|
||||
"eslint:common": "eslint ./test/**/*.common.js",
|
||||
"eslint:server": "eslint ./test/**/*.server.js",
|
||||
"eslint:browser": "eslint ./test/**/*.browser.js",
|
||||
"karma:firefox": "./node_modules/.bin/karma start --browsers=Firefox",
|
||||
"karma:chrome": "./node_modules/.bin/karma start --browsers=Chrome",
|
||||
"karma:ie": "./node_modules/.bin/karma start --browsers=IE",
|
||||
"karma:all": "./node_modules/.bin/karma start --browsers=PhantomJS,Chrome,Firefox",
|
||||
"packages": "npm list --depth=0",
|
||||
"package:purge": "rm -rf node_modules",
|
||||
"package:reinstall": "npm run package:purge && npm install",
|
||||
"package:check": "./node_modules/.bin/ncu",
|
||||
"package:upgrade": "./node_modules/.bin/ncu -u",
|
||||
"package:prod": "./node_modules/.bin/ncu -u",
|
||||
"package:dev": "./node_modules/.bin/ncu -p -u",
|
||||
"asset-server": "node config/webpack/webpack.hot.assets.config",
|
||||
"publish-patch": "git add -A && npm run dist && git commit && git push -u origin 4.1 && git push --tags && npm version patch && npm publish",
|
||||
"publish-minor": "git add -A && npm run dist && git commit && git push -u origin 4.1 && git push --tags && npm version minor && npm publish",
|
||||
"postpublish": "git push origin 4.1 --follow-tags"
|
||||
},
|
||||
"pre-commit": [
|
||||
"test"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/alchemy-fr/Phraseanet-production-client.git"
|
||||
},
|
||||
"keywords": [
|
||||
"phraseanet"
|
||||
],
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-core": "^6.25.0",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-stage-0": "^6.24.1",
|
||||
"chai": "^3.5.0",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"coveralls": "^2.13.1",
|
||||
"css-loader": "^0.28.4",
|
||||
"dotenv": "^4.0.0",
|
||||
"eslint": "^4.18.2",
|
||||
"eslint-config-airbnb": "^15.1.0",
|
||||
"eslint-loader": "^1.9.0",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-jsx-a11y": "^5.1.1",
|
||||
"eslint-plugin-react": "^7.1.0",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^0.11.2",
|
||||
"imports-loader": "^0.7.1",
|
||||
"istanbul-instrumenter-loader": "^3.0.0",
|
||||
"karma": "^1.7.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-cli": "^1.0.1",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-firefox-launcher": "^1.0.1",
|
||||
"karma-ie-launcher": "^1.0.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.3",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"karma-sinon": "^1.0.5",
|
||||
"karma-sinon-chai": "^1.3.1",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.31",
|
||||
"karma-webpack": "^2.0.4",
|
||||
"lodash": "^4.17.15",
|
||||
"lolex": "^2.1.2",
|
||||
"mocha": "^3.5.0",
|
||||
"node-sass": "^4.14.0",
|
||||
"nodemon": "^1.11.0",
|
||||
"npm-check-updates": "^2.12.1",
|
||||
"npmlog": "^4.1.2",
|
||||
"optimize-css-assets-webpack-plugin": "^3.0.0",
|
||||
"phantomjs-polyfill": "0.0.2",
|
||||
"phantomjs-prebuilt": "^2.1.16",
|
||||
"postcss-loader": "^2.0.6",
|
||||
"pre-commit": "^1.2.2",
|
||||
"resolve-url-loader": "^2.1.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"sass-loader": "^6.0.6",
|
||||
"sinon": "^2.1.0",
|
||||
"sinon-chai": "^2.12.0",
|
||||
"style-loader": "^0.18.2",
|
||||
"url-loader": "^0.5.9",
|
||||
"webpack": "^3.4.1",
|
||||
"webpack-dev-server": "^2.6.1",
|
||||
"webpack-notifier": "^1.5.0"
|
||||
},
|
||||
"babel": {
|
||||
"ignore": [
|
||||
"packages/babel-cli/src/babel-plugin/templates"
|
||||
]
|
||||
},
|
||||
"devEngines": {
|
||||
"node": ">=4.1 <6",
|
||||
"npm": ">=3.1 <5"
|
||||
},
|
||||
"author": {
|
||||
"name": "Florian Blouet",
|
||||
"email": "florian.blouet@gmail.com"
|
||||
},
|
||||
"bugs": "https://github.com/alchemy-fr/Phraseanet-production-client/issues",
|
||||
"homepage": "https://github.com/alchemy-fr/Phraseanet-production-client",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mapbox/mapbox-gl-language": "^0.9.2",
|
||||
"@turf/turf": "^5.1.6",
|
||||
"axios": "^0.19.2",
|
||||
"backbone": "^1.3.3",
|
||||
"blueimp-file-upload": "^9.15.0",
|
||||
"blueimp-load-image": "^2.14.0",
|
||||
"bootstrap-multiselect": "^0.9.13-1",
|
||||
"bootstrap-sass": "^2.3.2",
|
||||
"es6-promise": "^4.1.1",
|
||||
"geonames-server-jquery-plugin": "^0.2.2",
|
||||
"humane-js": "^3.2.2",
|
||||
"i18next": "^8.4.3",
|
||||
"i18next-xhr-backend": "^1.4.2",
|
||||
"jquery": "^3.2.1",
|
||||
"jquery-lazyload": "^1.9.7",
|
||||
"jquery-treeview": "https://github.com/alchemy-fr/jquery-treeview.git",
|
||||
"jquery-ui": "^1.10.4",
|
||||
"jquery-ui-datepicker-with-i18n": "^1.10.4",
|
||||
"jquery.fancytree": "~2.7",
|
||||
"jquery.tree": "0.0.5",
|
||||
"js-cookie": "^2.1.0",
|
||||
"leaflet": "^0.7.7",
|
||||
"leaflet-contextmenu": "^1.0.0",
|
||||
"leaflet-draw": "^0.3.0",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"mapbox": "^1.0.0-beta10",
|
||||
"mapbox-gl": "^1.11.0",
|
||||
"mapbox-gl-circle": "^1.6.5",
|
||||
"mapbox.js": "^2.4.0",
|
||||
"nouislider": "^9.2.0",
|
||||
"pym.js": "^1.3.1",
|
||||
"rx": "^4.1.0",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"underscore": "^1.8.3",
|
||||
"video.js": "^7.5.5",
|
||||
"videojs-flash": "^2.1.0",
|
||||
"videojs-hotkeys": "^0.2.20",
|
||||
"zxcvbn": "^4.4.2"
|
||||
}
|
||||
}
|
74
Phraseanet-production-client/src/account/bootstrap.js
vendored
Normal file
74
Phraseanet-production-client/src/account/bootstrap.js
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import $ from 'jquery';
|
||||
import ConfigService from './../components/core/configService';
|
||||
import LocaleService from '../components/locale';
|
||||
import merge from 'lodash.merge';
|
||||
import defaultConfig from './config';
|
||||
import Emitter from '../components/core/emitter';
|
||||
import account from './../components/account';
|
||||
|
||||
$(document).ready(() => {
|
||||
// hide or show callback url input whether user choose a web or dektop application
|
||||
$('#form_create input[name=type]').bind('click', function () {
|
||||
if ($(this).val() === 'desktop') {
|
||||
$('#form_create .callback-control-group').hide().find('input').val('');
|
||||
} else {
|
||||
$('#form_create .callback-control-group').show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
class Bootstrap {
|
||||
|
||||
app;
|
||||
configService;
|
||||
localeService;
|
||||
appServices;
|
||||
|
||||
constructor(userConfig) {
|
||||
const configuration = merge({}, defaultConfig, userConfig);
|
||||
|
||||
this.appEvents = new Emitter();
|
||||
this.configService = new ConfigService(configuration);
|
||||
this.onConfigReady();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
onConfigReady() {
|
||||
this.appServices = {
|
||||
configService: this.configService,
|
||||
localeService: this.localeService,
|
||||
appEvents: this.appEvents
|
||||
};
|
||||
|
||||
/**
|
||||
* add components
|
||||
*/
|
||||
|
||||
$(document).ready(() => {
|
||||
let accountService = account(this.appServices);
|
||||
|
||||
accountService.initialize({
|
||||
$container: $('body')
|
||||
});
|
||||
|
||||
switch (this.configService.get('state')) {
|
||||
case 'editAccount':
|
||||
accountService.editAccount();
|
||||
break;
|
||||
case 'editSession':
|
||||
accountService.editSession();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const bootstrap = (userConfig) => {
|
||||
return new Bootstrap(userConfig);
|
||||
};
|
||||
|
||||
export default bootstrap;
|
7
Phraseanet-production-client/src/account/config.js
Normal file
7
Phraseanet-production-client/src/account/config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
let defaultConfig = {
|
||||
locale: 'fr',
|
||||
basePath: '/',
|
||||
translations: '/prod/language.json',
|
||||
};
|
||||
|
||||
export default defaultConfig;
|
10
Phraseanet-production-client/src/account/index.js
Normal file
10
Phraseanet-production-client/src/account/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import bootstrap from './bootstrap';
|
||||
let accountApp = {
|
||||
bootstrap
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.accountApp = accountApp;
|
||||
}
|
||||
|
||||
module.exports = accountApp;
|
86
Phraseanet-production-client/src/authenticate/bootstrap.js
vendored
Normal file
86
Phraseanet-production-client/src/authenticate/bootstrap.js
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
import $ from 'jquery';
|
||||
import ConfigService from './../components/core/configService';
|
||||
import LocaleService from '../components/locale';
|
||||
import merge from 'lodash.merge';
|
||||
|
||||
import defaultConfig from './config';
|
||||
import Emitter from '../components/core/emitter';
|
||||
import authentication from './../components/authentication';
|
||||
|
||||
class Bootstrap {
|
||||
|
||||
app;
|
||||
configService;
|
||||
localeService;
|
||||
appServices;
|
||||
|
||||
constructor(userConfig) {
|
||||
|
||||
const configuration = merge({}, defaultConfig, userConfig);
|
||||
|
||||
this.appEvents = new Emitter();
|
||||
this.configService = new ConfigService(configuration);
|
||||
this.localeService = new LocaleService({
|
||||
configService: this.configService
|
||||
});
|
||||
|
||||
this.localeService.fetchTranslations()
|
||||
.then(() => {
|
||||
this.onConfigReady();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
onConfigReady() {
|
||||
this.appServices = {
|
||||
configService: this.configService,
|
||||
localeService: this.localeService,
|
||||
appEvents: this.appEvents
|
||||
};
|
||||
|
||||
// export translation for backward compatibility:
|
||||
// window.language = this.localeService.getTranslations();
|
||||
|
||||
/**
|
||||
* add components
|
||||
*/
|
||||
|
||||
$(document).ready(() => {
|
||||
let authService = authentication(this.appServices);
|
||||
|
||||
authService.initialize();
|
||||
|
||||
switch (this.configService.get('state')) {
|
||||
case 'login':
|
||||
authService.login();
|
||||
break;
|
||||
case 'forgotPassword':
|
||||
authService.forgotPassword();
|
||||
break;
|
||||
case 'renewPassword':
|
||||
authService.renewPassword();
|
||||
break;
|
||||
case 'register':
|
||||
authService.register();
|
||||
break;
|
||||
case 'registerProvider':
|
||||
authService.registerProvider();
|
||||
break;
|
||||
case 'renewEmail':
|
||||
authService.renewEmail();
|
||||
break;
|
||||
case 'changePassword':
|
||||
authService.changePassword();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const bootstrap = (userConfig) => {
|
||||
return new Bootstrap(userConfig);
|
||||
};
|
||||
|
||||
export default bootstrap;
|
7
Phraseanet-production-client/src/authenticate/config.js
Normal file
7
Phraseanet-production-client/src/authenticate/config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
let defaultConfig = {
|
||||
locale: 'fr',
|
||||
basePath: '/',
|
||||
translations: '/login/language.json',
|
||||
};
|
||||
|
||||
export default defaultConfig;
|
10
Phraseanet-production-client/src/authenticate/index.js
Normal file
10
Phraseanet-production-client/src/authenticate/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import bootstrap from './bootstrap';
|
||||
let authenticateApp = {
|
||||
bootstrap
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.authenticateApp = authenticateApp;
|
||||
}
|
||||
|
||||
module.exports = authenticateApp;
|
236
Phraseanet-production-client/src/components/account/index.js
Normal file
236
Phraseanet-production-client/src/components/account/index.js
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import geonames from './../authentication/common/geonames';
|
||||
const account = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
|
||||
const initialize = (options) => {
|
||||
let {$container} = options;
|
||||
$container.on('click', '.alert .alert-block-close a', function (e) {
|
||||
e.preventDefault();
|
||||
$(this).closest('.alert').alert('close');
|
||||
return false;
|
||||
});
|
||||
|
||||
// revoke third party application access
|
||||
$('a.app-btn').bind('click', function (e) {
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $this.attr('href'),
|
||||
dataType: 'json',
|
||||
data: {revoke: $this.hasClass('authorize') ? 0 : 1},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
var li = $this.closest('li');
|
||||
|
||||
var hidden = $('.app-btn.hidden , .status.hidden', li);
|
||||
var notHidden = $('.app-btn:not(.hidden), .status:not(.hidden)', li);
|
||||
|
||||
hidden.removeClass('hidden');
|
||||
notHidden.addClass('hidden');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// generate new access token
|
||||
$('a#generate_access').bind('click', function (e) {
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: $this.attr('href'),
|
||||
dataType: 'json',
|
||||
data: {
|
||||
usr_id: $this.closest('div').attr('id')
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
$('#my_access_token').empty().append(data.token);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//modify application callback url
|
||||
$('.modifier_callback').bind('click', function () {
|
||||
var modifierBtn = $(this);
|
||||
var saveBtn = $('a.save_callback');
|
||||
var input = $('.url_callback_input');
|
||||
var inputVal = input.html();
|
||||
|
||||
modifierBtn.hide();
|
||||
saveBtn.show();
|
||||
// wrapp current calback in an input
|
||||
input
|
||||
.empty()
|
||||
.wrapInner(''
|
||||
+ '<input value="' + inputVal + '"'
|
||||
+ ' name="oauth_callback" size="50" type="text"/>'
|
||||
);
|
||||
|
||||
$('.url_callback').off();
|
||||
|
||||
// save new callback
|
||||
saveBtn.bind('click', function (e) {
|
||||
e.preventDefault();
|
||||
var callback = $('input[name=oauth_callback]').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: saveBtn.attr('href'),
|
||||
dataType: 'json',
|
||||
data: {callback: callback},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
input.empty().append(callback);
|
||||
} else {
|
||||
input.empty().append(inputVal);
|
||||
}
|
||||
|
||||
modifierBtn.show();
|
||||
saveBtn.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
//modify application webhook url
|
||||
$('.webhook-modify-btn').bind('click', function () {
|
||||
var modifierBtn = $(this);
|
||||
var saveBtn = $('a.save_webhook');
|
||||
var input = $('.url_webhook_input');
|
||||
var inputVal = input.html();
|
||||
|
||||
modifierBtn.hide();
|
||||
saveBtn.show();
|
||||
// wrapp current calback in an input
|
||||
input
|
||||
.empty()
|
||||
.wrapInner(''
|
||||
+ '<input value="' + inputVal + '"'
|
||||
+ ' name="oauth_webhook" size="50" type="text"/>'
|
||||
);
|
||||
|
||||
$('.url_webhook').off();
|
||||
|
||||
// save new callback
|
||||
saveBtn.bind('click', function (e) {
|
||||
e.preventDefault();
|
||||
var webhook = $('input[name=oauth_webhook]').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: saveBtn.attr('href'),
|
||||
dataType: 'json',
|
||||
data: {webhook: webhook},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
input.empty().append(webhook);
|
||||
} else {
|
||||
input.empty().append(inputVal);
|
||||
}
|
||||
|
||||
modifierBtn.show();
|
||||
saveBtn.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// hide or show callback url input whether user choose a web or dektop application
|
||||
/* $('#form_create input[name=type]').bind('click', function () {
|
||||
if ($(this).val() === 'desktop') {
|
||||
$('#form_create .callback-control-group').hide().find('input').val('');
|
||||
} else {
|
||||
$('#form_create .callback-control-group').show();
|
||||
}
|
||||
});*/
|
||||
|
||||
// authorize password grant type or not
|
||||
$('.grant-type').bind('click', function () {
|
||||
var $this = $(this);
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: $this.attr('value'),
|
||||
dataType: 'json',
|
||||
data: {grant: $this.is(':checked') ? '1' : '0'},
|
||||
success: function (data) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// delete an application
|
||||
/* $('a.delete-app').bind('click', function (e) {
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var li = $this.closest('li');
|
||||
|
||||
$.ajax({
|
||||
type: 'DELETE',
|
||||
url: $this.attr('href'),
|
||||
dataType: 'json',
|
||||
data: {},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
li.find('.modal').modal('hide');
|
||||
li.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
});*/
|
||||
};
|
||||
|
||||
const editAccount = () => {
|
||||
$('legend').bind('click', function () {
|
||||
$('.form-info').hide(200);
|
||||
$($(this).data('target')).show();
|
||||
});
|
||||
|
||||
geonames.init($('#form_geonameid'), {
|
||||
server: configService.get('geonameServerUrl'),
|
||||
limit: 40
|
||||
});
|
||||
};
|
||||
|
||||
const editSession = () => {
|
||||
var modal = $('#modal-delete-confirm').modal({
|
||||
show: false
|
||||
});
|
||||
|
||||
$('a.delete-session').bind('click', function (e) {
|
||||
e.preventDefault();
|
||||
modal
|
||||
.data('delete-url', $(this).prop('href'))
|
||||
.modal('toggle');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('a.confirm-delete').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: modal.data('delete-url'),
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
$('#row-' + data.session_id).closest('tr').remove();
|
||||
}
|
||||
modal.modal('toggle');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize, editAccount, editSession}
|
||||
};
|
||||
export default account;
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import RenewPasswordForm from './common/forms/views/formType/passwordSetter';
|
||||
|
||||
const changePassword = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const initialize = () => {
|
||||
|
||||
require.ensure([], () => {
|
||||
services.zxcvbn = require('zxcvbn');
|
||||
new RenewPasswordForm({
|
||||
services,
|
||||
el: $('form[name=passwordChangeForm]'),
|
||||
rules: [
|
||||
{
|
||||
name: 'oldPassword',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'password[password]',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'password[password]',
|
||||
rules: 'min_length[5]',
|
||||
message: localeService.t('validation_length_min', {
|
||||
postProcess: 'sprintf',
|
||||
sprintf: ['5']
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'password[confirm]',
|
||||
rules: 'matches[password[password]]',
|
||||
message: localeService.t('password_match')
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
export default changePassword;
|
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
var FormValidator = function (rules, handlers) {
|
||||
// rules setted by user
|
||||
this.rules = rules || [];
|
||||
// custom callbacks
|
||||
this.handlers = handlers || [];
|
||||
// final fields to validate
|
||||
this.fields = [];
|
||||
|
||||
var self = this;
|
||||
|
||||
_.each(this.rules, function (field) {
|
||||
if ('name' in field && 'rules' in field) {
|
||||
self._addField(field);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Validate method, argument is the serialize form
|
||||
FormValidator.prototype.validate = function (inputs) {
|
||||
var self = this;
|
||||
// possible errors
|
||||
this.errors = [];
|
||||
// inputs present in form
|
||||
this.inputs = {};
|
||||
|
||||
_.each(_.groupBy(inputs, function (input) {
|
||||
return input.name;
|
||||
}), function (fields, name) {
|
||||
self.inputs[name] = fields;
|
||||
});
|
||||
|
||||
this._validateForm();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
FormValidator.prototype.getErrors = function () {
|
||||
return this.errors;
|
||||
};
|
||||
|
||||
FormValidator.prototype.hasErrors = function () {
|
||||
return this.errors.length > 0;
|
||||
};
|
||||
|
||||
FormValidator.prototype.getRules = function () {
|
||||
return this.rules;
|
||||
};
|
||||
|
||||
FormValidator.prototype._addField = function (field) {
|
||||
this.fields.push({
|
||||
name: field.name,
|
||||
rules: field.rules,
|
||||
message: field.message || 'An error ocurred on input[name=' + field.name + '], you can edit this message by setting a "message" property in your rule definition object',
|
||||
value: null,
|
||||
type: field.type || 'text'
|
||||
});
|
||||
};
|
||||
|
||||
FormValidator.prototype._validateForm = function () {
|
||||
var self = this;
|
||||
this.errors = [];
|
||||
_.each(this.fields, function (field) {
|
||||
if (_.has(self.inputs, field.name)) {
|
||||
// values can be multiple
|
||||
var values = [];
|
||||
|
||||
_.each(self.inputs[field.name], function (field) {
|
||||
return values.push(field.value);
|
||||
});
|
||||
|
||||
field.value = values.join(',');
|
||||
|
||||
self._validateField(field);
|
||||
} else if (field.type === 'checkbox' || field.type === 'radio' || field.type === 'select' || field.type === 'multiple') {
|
||||
field.value = '';
|
||||
self._validateField(field);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
FormValidator.prototype._validateField = function (field) {
|
||||
var self = this;
|
||||
var ruleRegex = /^(.+?)\[(.+)\]$/;
|
||||
var rules = field.rules.split('|');
|
||||
|
||||
// Run through the rules and execute the validation methods as needed
|
||||
_.every(rules, function (method) {
|
||||
var param = null;
|
||||
var failed = false;
|
||||
var parts = ruleRegex.exec(method);
|
||||
|
||||
// If the rule has a parameter (i.e. matches[param]) split it out
|
||||
if (parts) {
|
||||
method = parts[1];
|
||||
param = parts[2];
|
||||
}
|
||||
|
||||
// If the hook is defined, run it to find any validation errors
|
||||
if (typeof self._hooks[method] === 'function') {
|
||||
if (!self._hooks[method].apply(self, [field, param])) {
|
||||
failed = true;
|
||||
}
|
||||
} else if (method.substring(0, 9) === 'callback_') {
|
||||
// Custom method. Execute the handler if it was registered
|
||||
method = method.substring(9, method.length);
|
||||
|
||||
if (typeof self.handlers[method] === 'function') {
|
||||
if (this.handlers[method].apply(self, [field.value, param]) === false) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the hook failed, add a message to the errors array
|
||||
if (failed) {
|
||||
self.errors.push({
|
||||
name: field.name,
|
||||
value: field.value,
|
||||
message: field.message,
|
||||
rule: method
|
||||
});
|
||||
}
|
||||
|
||||
// Breaks loop iteration
|
||||
return failed;
|
||||
});
|
||||
};
|
||||
|
||||
FormValidator.prototype.Regexp = {
|
||||
numericRegex: /^[0-9]+$/,
|
||||
integerRegex: /^\-?[0-9]+$/,
|
||||
decimalRegex: /^\-?[0-9]*\.?[0-9]+$/,
|
||||
emailRegex: /^[^@]+@[^@]+\.[^@]+$/,
|
||||
alphaRegex: /^[a-z]+$/i,
|
||||
alphaNumericRegex: /^[a-z0-9]+$/i,
|
||||
alphaDashRegex: /^[a-z0-9_\-]+$/i,
|
||||
naturalRegex: /^[0-9]+$/i,
|
||||
naturalNoZeroRegex: /^[1-9][0-9]*$/i,
|
||||
// IP v6 a v4 or hostname, by Mikulas Dite see http://stackoverflow.com/a/9209720/96656
|
||||
ipRegex: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^(?:(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-fA-F]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,1}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,2}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,3}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:[0-9a-fA-F]{1,4})):)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,4}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,5}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,6}(?:(?:[0-9a-fA-F]{1,4})))?::))))$/i,
|
||||
numericDashRegex: /^[\d\-\s]+$/,
|
||||
urlRegex: /^((http|https):\/\/(\w+:{0,1}\w*@)?(\S+)|)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/
|
||||
};
|
||||
|
||||
// Object containing all of the validation hooks
|
||||
FormValidator.prototype._hooks = {
|
||||
required: function (field) {
|
||||
var value = field.value;
|
||||
|
||||
return (value !== null && value !== '');
|
||||
},
|
||||
equal: function (field, defaultName) {
|
||||
return field.value === defaultName;
|
||||
},
|
||||
matches: function (field, matchName) {
|
||||
if (typeof this.inputs[matchName] === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
var el = this.inputs[matchName].shift();
|
||||
|
||||
if (el) {
|
||||
return field.value === el.value;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
valid_email: function (field) {
|
||||
return this.Regexp.emailRegex.test(field.value);
|
||||
},
|
||||
valid_emails: function (field) {
|
||||
var result = field.value.split(',');
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
if (!this.Regexp.emailRegex.test($.trim(result[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
min_length: function (field, length) {
|
||||
if (field.type === 'multiple') {
|
||||
return _.filter(field.value.split(','), function (value) {
|
||||
return value !== '';
|
||||
}).length >= parseInt(length, 10)
|
||||
}
|
||||
|
||||
if (!this.Regexp.numericRegex.test(length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (field.value.length >= parseInt(length, 10));
|
||||
},
|
||||
max_length: function (field, length) {
|
||||
if (field.type === 'multiple') {
|
||||
return _.filter(field.value.split(','), function (value) {
|
||||
return value !== '';
|
||||
}).length <= parseInt(length, 10)
|
||||
}
|
||||
|
||||
if (!this.Regexp.numericRegex.test(length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (field.value.length <= parseInt(length, 10));
|
||||
},
|
||||
exact_length: function (field, length) {
|
||||
if (field.type === 'multiple') {
|
||||
return _.filter(field.value.split(','), function (value) {
|
||||
return value !== '';
|
||||
}).length === parseInt(length, 10)
|
||||
}
|
||||
|
||||
if (!this.Regexp.numericRegex.test(length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (field.value.length === parseInt(length, 10));
|
||||
},
|
||||
greater_than: function (field, param) {
|
||||
if (!this.Regexp.decimalRegex.test(field.value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (parseFloat(field.value) > parseFloat(param));
|
||||
},
|
||||
less_than: function (field, param) {
|
||||
if (!this.Regexp.decimalRegex.test(field.value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (parseFloat(field.value) < parseFloat(param));
|
||||
},
|
||||
alpha: function (field) {
|
||||
return (this.Regexp.alphaRegex.test(field.value));
|
||||
},
|
||||
alpha_numeric: function (field) {
|
||||
return (this.Regexp.alphaNumericRegex.test(field.value));
|
||||
},
|
||||
alpha_dash: function (field) {
|
||||
return (this.Regexp.alphaDashRegex.test(field.value));
|
||||
},
|
||||
numeric: function (field) {
|
||||
return (this.Regexp.numericRegex.test(field.value));
|
||||
},
|
||||
integer: function (field) {
|
||||
return (this.Regexp.integerRegex.test(field.value));
|
||||
},
|
||||
decimal: function (field) {
|
||||
return (this.Regexp.decimalRegex.test(field.value));
|
||||
},
|
||||
is_natural: function (field) {
|
||||
return (this.Regexp.naturalRegex.test(field.value));
|
||||
},
|
||||
is_natural_no_zero: function (field) {
|
||||
return (this.Regexp.naturalNoZeroRegex.test(field.value));
|
||||
},
|
||||
valid_ip: function (field) {
|
||||
return (this.Regexp.ipRegex.test(field.value));
|
||||
},
|
||||
valid_url: function (field) {
|
||||
return (this.Regexp.urlRegex.test(field.value));
|
||||
}
|
||||
};
|
||||
|
||||
export default FormValidator;
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import Backbone from 'backbone';
|
||||
var ErrorView = Backbone.View.extend({
|
||||
tagName: 'div',
|
||||
initialize: function (options) {
|
||||
options = options || {};
|
||||
|
||||
if (options.name === undefined) {
|
||||
throw 'Missing name attribute in error view';
|
||||
}
|
||||
|
||||
if (options.errorTemplate === undefined) {
|
||||
throw 'Missing errorTemplate attribute in error view';
|
||||
}
|
||||
|
||||
this.name = options.name;
|
||||
this.errorTemplate = options.errorTemplate;
|
||||
|
||||
this.errors = options.errors || {};
|
||||
this.onRenderError = options.onRenderError || null;
|
||||
},
|
||||
render: function () {
|
||||
if (this.errors.length > 0) {
|
||||
var template = _.template($(this.errorTemplate).html(), {
|
||||
errors: this.errors
|
||||
});
|
||||
|
||||
this.$el.html(template);
|
||||
|
||||
if (_.isFunction(this.onRenderError)) {
|
||||
this.onRenderError(this.name, this.$el);
|
||||
}
|
||||
} else {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
renderErrors: function (errors) {
|
||||
this.errors = errors;
|
||||
this.render();
|
||||
|
||||
return this;
|
||||
},
|
||||
reset: function () {
|
||||
this.$el.empty();
|
||||
}
|
||||
});
|
||||
|
||||
export default ErrorView;
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import Backbone from 'backbone';
|
||||
import Validator from './../validator';
|
||||
import InputView from './input';
|
||||
var Form = Backbone.View.extend({
|
||||
events: {
|
||||
submit: '_onSubmit'
|
||||
},
|
||||
initialize: function (options) {
|
||||
options = options || {};
|
||||
|
||||
var self = this;
|
||||
|
||||
if (options.services !== undefined) {
|
||||
this.services = options.services;
|
||||
}
|
||||
|
||||
this.errorTemplate = options.errorTemplate || '#field_errors';
|
||||
this.onRenderError = options.onRenderError || null;
|
||||
// get a new validator defined rules
|
||||
this.validator = new Validator(options.rules || []);
|
||||
|
||||
this.inputViews = {};
|
||||
|
||||
// creates input views for each input
|
||||
_.each(this.$el.serializeArray(), function (input) {
|
||||
self._addInputView(input);
|
||||
});
|
||||
},
|
||||
_onSubmit: function (event) {
|
||||
var self = this;
|
||||
|
||||
// reset previous errors in the view
|
||||
this._resetInputErrors();
|
||||
|
||||
// validate new values
|
||||
this.validator.validate(this.$el.serializeArray());
|
||||
|
||||
if (this.validator.hasErrors()) {
|
||||
// cancel submit
|
||||
event.preventDefault();
|
||||
// group errors by input
|
||||
_.each(_.groupBy(this.validator.getErrors(), function (error) {
|
||||
return error.name;
|
||||
}), function (errors, name) {
|
||||
// show new errors in the views
|
||||
if (name in self.inputViews) {
|
||||
self.inputViews[name].showErrors(errors);
|
||||
} else {
|
||||
// Because serialize array do not serialize non checked input
|
||||
// We must create view for errored input name on the fly
|
||||
var input = {name: name};
|
||||
|
||||
self._addInputView(input);
|
||||
self.inputViews[name].showErrors(errors);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
_resetInputErrors: function () {
|
||||
_.each(this.inputViews, function (view) {
|
||||
view.resetErrors();
|
||||
});
|
||||
},
|
||||
_addInputView: function (input) {
|
||||
var name = input.name;
|
||||
|
||||
this.inputViews[name] = new InputView({
|
||||
name: name,
|
||||
el: $('input[name="' + name + '"], select[name="' + name + '"], textarea[name="' + name + '"]', this.$el).first().closest('div'),
|
||||
errorTemplate: this.errorTemplate,
|
||||
onRenderError: this.onRenderError
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
export default Form;
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import FormView from './../form';
|
||||
|
||||
var PasswordSetterForm = FormView.extend({
|
||||
events: function () {
|
||||
return _.extend({}, FormView.prototype.events, {
|
||||
'keyup input[type=password]': 'onPasswordKeyup'
|
||||
});
|
||||
},
|
||||
onPasswordKeyup: function (event) {
|
||||
var input = $(event.target);
|
||||
var password = input.val();
|
||||
var inputView = this.inputViews[input.attr('name')];
|
||||
var bg = $('.password_strength_bg', inputView.$el);
|
||||
var label = $('.password_strength_label', inputView.$el);
|
||||
var desc = $('.password_strength_desc', inputView.$el);
|
||||
var css = {
|
||||
width: '0%',
|
||||
'background-color': 'rgb(39, 39, 30)'
|
||||
};
|
||||
var result = '';
|
||||
|
||||
if (password.length > 0) {
|
||||
var passMeter = this.services.zxcvbn(input.val());
|
||||
|
||||
switch (passMeter.score) {
|
||||
case 0:
|
||||
case 1:
|
||||
css = {
|
||||
width: '25%',
|
||||
'background-color': 'rgb(200, 24, 24)'
|
||||
};
|
||||
result = this.services.localeService.t('weak');
|
||||
break;
|
||||
case 2:
|
||||
css = {
|
||||
width: '50%',
|
||||
'background-color': 'rgb(255, 172, 29)'
|
||||
};
|
||||
result = this.services.localeService.t('ordinary');
|
||||
break;
|
||||
case 3:
|
||||
css = {
|
||||
width: '75%',
|
||||
'background-color': 'rgb(166, 192, 96)'
|
||||
};
|
||||
result = this.services.localeService.t('good');
|
||||
break;
|
||||
case 4:
|
||||
css = {
|
||||
width: '100%',
|
||||
'background-color': 'rgb(39, 179, 15)'
|
||||
};
|
||||
result = this.services.localeService.t('great');
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
bg.css(css);
|
||||
label.css({color: css['background-color']});
|
||||
desc.css({color: css['background-color']}).html(result);
|
||||
}
|
||||
});
|
||||
|
||||
export default PasswordSetterForm;
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import Backbone from 'backbone';
|
||||
import ErrorView from './error';
|
||||
import MultiViews from './../../multiviews';
|
||||
var InputView = Backbone.View.extend(_.extend({}, MultiViews, {
|
||||
initialize: function (options) {
|
||||
options = options || {};
|
||||
if (options.name === undefined) {
|
||||
throw 'Missing name attribute in input view';
|
||||
}
|
||||
|
||||
if (options.errorTemplate === undefined) {
|
||||
throw 'Missing errorTemplate attribute in input view';
|
||||
}
|
||||
|
||||
this.name = options.name;
|
||||
|
||||
this.errorView = new ErrorView({
|
||||
name: this.name,
|
||||
errorTemplate: options.errorTemplate,
|
||||
onRenderError: options.onRenderError || null
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
this._assignView({'.error-view': this.errorView});
|
||||
},
|
||||
showErrors: function (errors) {
|
||||
this.render();
|
||||
|
||||
this.errorView.renderErrors(errors);
|
||||
|
||||
return this;
|
||||
},
|
||||
resetErrors: function () {
|
||||
this.errorView.reset();
|
||||
}
|
||||
}));
|
||||
|
||||
export default InputView;
|
@@ -0,0 +1,43 @@
|
||||
import $ from 'jquery';
|
||||
require('jquery-ui');
|
||||
require('geonames-server-jquery-plugin/jquery.geonames.js');
|
||||
const geonames = {
|
||||
|
||||
init: function ($field, options) {
|
||||
var geocompleter = $field.geocompleter(options);
|
||||
|
||||
// On focus add select-state
|
||||
geocompleter.geocompleter('autocompleter', 'on', 'autocompletefocus', function (event, ui) {
|
||||
$('li', $(event.originalEvent.target)).closest('li').removeClass('selected');
|
||||
$('a.ui-state-active, a.ui-state-hover, a.ui-state-focus', $(event.originalEvent.target)).closest('li').addClass('selected');
|
||||
});
|
||||
|
||||
// On search request add loading-state
|
||||
geocompleter.geocompleter('autocompleter', 'on', 'autocompletesearch', function (event, ui) {
|
||||
$(this).attr('autocomplete', 'false');
|
||||
$(this).addClass('input-loading');
|
||||
$(this).removeClass('input-error');
|
||||
});
|
||||
|
||||
// On response remove loading-state
|
||||
geocompleter.geocompleter('autocompleter', 'on', 'autocompleteresponse', function (event, ui) {
|
||||
$(this).removeClass('input-loading');
|
||||
});
|
||||
|
||||
// On close menu remove loading-state
|
||||
geocompleter.geocompleter('autocompleter', 'on', 'autocompleteclose', function (event, ui) {
|
||||
$(this).removeClass('input-loading');
|
||||
});
|
||||
|
||||
// On request error add error-state
|
||||
geocompleter.geocompleter('autocompleter', 'on', 'geotocompleter.request.error', function (jqXhr, status, error) {
|
||||
$(this).removeClass('input-loading');
|
||||
$(this).addClass('input-error');
|
||||
});
|
||||
|
||||
return geocompleter;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default geonames;
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import _ from 'underscore';
|
||||
export default {
|
||||
// bind a subview to a DOM element
|
||||
_assignView: function (selector, view) {
|
||||
var selectors;
|
||||
if (_.isObject(selector)) {
|
||||
selectors = selector;
|
||||
} else {
|
||||
selectors = {};
|
||||
selectors[selector] = view;
|
||||
}
|
||||
if (!selectors) return;
|
||||
_.each(selectors, function (view, selector) {
|
||||
view.setElement(this.$(selector)).render();
|
||||
}, this);
|
||||
}
|
||||
};
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import ForgotPassWordForm from './common/forms/views/form';
|
||||
|
||||
const forgotPassword = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const initialize = () => {
|
||||
new ForgotPassWordForm({
|
||||
el: $('form[name=forgottenPasswordForm]'),
|
||||
rules: [
|
||||
{
|
||||
name: 'email',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
rules: 'valid_email',
|
||||
message: localeService.t('validation_email')
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
export default forgotPassword;
|
||||
|
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import loginService from './login';
|
||||
import forgotPasswordService from './forgotPassword';
|
||||
import renewPasswordService from './renewPassword';
|
||||
import registerService from './register';
|
||||
import registerProviderService from './registerProvider';
|
||||
import renewEmailService from './renewEmail';
|
||||
import changePasswordService from './changePassword';
|
||||
require('bootstrap-multiselect'); // multiselect
|
||||
|
||||
const authentication = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
|
||||
const initialize = () => {
|
||||
// close alerts
|
||||
$(document).on('click', '.alert .alert-block-close a', function (e) {
|
||||
e.preventDefault();
|
||||
$(this).closest('.alert').alert('close');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('select[multiple="multiple"]').multiselect({
|
||||
buttonWidth: '100%',
|
||||
buttonClass: 'btn btn-inverse',
|
||||
maxHeight: 185,
|
||||
includeSelectAllOption: true,
|
||||
selectAllValue: 'all',
|
||||
selectAllText: localeService.t('all_collections'),
|
||||
buttonText: function (options, select) {
|
||||
if (options.length === 0) {
|
||||
return localeService.t('no_collection_selected') + '<b class="caret"></b>';
|
||||
} else {
|
||||
return localeService.t(
|
||||
options.length === 1 ? 'one_collection_selected' : 'collections_selected', {
|
||||
postProcess: 'sprintf',
|
||||
sprintf: [options.length]
|
||||
}) + ' <b class="caret"></b>';
|
||||
}
|
||||
}
|
||||
});
|
||||
$('form[name="registerForm"]').on('submit', function () {
|
||||
// must deselect the 'select all' checkbox for server side validation.
|
||||
$('select[multiple="multiple"]').multiselect('deselect', 'all');
|
||||
});
|
||||
};
|
||||
|
||||
const login = () => {
|
||||
// init login form
|
||||
loginService(services).initialize();
|
||||
};
|
||||
const forgotPassword = () => {
|
||||
// init login form
|
||||
forgotPasswordService(services).initialize();
|
||||
};
|
||||
const renewPassword = () => {
|
||||
// init login form
|
||||
renewPasswordService(services).initialize();
|
||||
};
|
||||
const register = () => {
|
||||
// init login form
|
||||
registerService(services).initialize();
|
||||
};
|
||||
const registerProvider = () => {
|
||||
// init login form
|
||||
registerProviderService(services).initialize();
|
||||
};
|
||||
const renewEmail = () => {
|
||||
// init login form
|
||||
renewEmailService(services).initialize();
|
||||
};
|
||||
const changePassword = () => {
|
||||
// init login form
|
||||
changePasswordService(services).initialize();
|
||||
};
|
||||
|
||||
return { initialize, login, forgotPassword, renewPassword, register, registerProvider, renewEmail, changePassword}
|
||||
};
|
||||
export default authentication;
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import LoginForm from './common/forms/views/form';
|
||||
|
||||
const login = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const initialize = () => {
|
||||
|
||||
new LoginForm({
|
||||
el: $('form[name=loginForm]'),
|
||||
rules: [
|
||||
{
|
||||
name: 'login',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
export default login;
|
||||
|
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// launch application
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import RegisterForm from './common/forms/views/formType/passwordSetter';
|
||||
import geonames from './common/geonames';
|
||||
|
||||
const regiser = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const initialize = () => {
|
||||
var fieldsConfiguration = [];
|
||||
|
||||
$.when.apply($, [
|
||||
$.ajax({
|
||||
url: '/login/registration-fields/',
|
||||
success: function (config) {
|
||||
fieldsConfiguration = config;
|
||||
}
|
||||
})
|
||||
]).done(function () {
|
||||
|
||||
var rules = [];
|
||||
var defaultRules = [
|
||||
{
|
||||
name: 'email',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
rules: 'valid_email',
|
||||
message: localeService.t('validation_email')
|
||||
},
|
||||
{
|
||||
name: 'password[password]',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'password[password]',
|
||||
rules: 'min_length[5]',
|
||||
message: localeService.t('validation_length_min', {
|
||||
postProcess: 'sprintf',
|
||||
sprintf: ['5']
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'password[confirm]',
|
||||
rules: 'matches[password[password]]',
|
||||
message: localeService.t('password_match')
|
||||
},
|
||||
{
|
||||
name: 'accept-tou',
|
||||
rules: 'required',
|
||||
message: localeService.t('accept_tou'),
|
||||
type: 'checkbox'
|
||||
},
|
||||
{
|
||||
name: 'collections[]',
|
||||
rules: 'min_length[1]',
|
||||
message: localeService.t('validation_choice_min', {
|
||||
postProcess: 'sprintf',
|
||||
sprintf: ['1']
|
||||
}),
|
||||
type: 'multiple'
|
||||
}
|
||||
];
|
||||
|
||||
_.each(fieldsConfiguration, function (field) {
|
||||
if (field.required) {
|
||||
var rule = {
|
||||
name: field.name,
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
};
|
||||
|
||||
defaultRules.push(rule);
|
||||
}
|
||||
});
|
||||
|
||||
_.each(defaultRules, function (rule) {
|
||||
// add rule if element exists
|
||||
if ($('[name="' + rule.name + '"]').length >= 1) {
|
||||
}
|
||||
});
|
||||
|
||||
var $form = $('form[name=registerForm]');
|
||||
|
||||
require.ensure([], () => {
|
||||
services.zxcvbn = require('zxcvbn');
|
||||
new RegisterForm({
|
||||
el: $form,
|
||||
rules: rules,
|
||||
services
|
||||
});
|
||||
});
|
||||
|
||||
var geocompleter = geonames.init($('#geonameid'), {
|
||||
server: $form.data('geonames-server-adress'),
|
||||
limit: 40,
|
||||
'init-input': false,
|
||||
onInit: function (input, autoinput) {
|
||||
// Set default name to geonameid-completer
|
||||
autoinput.prop('name', 'geonameid-completer');
|
||||
}
|
||||
});
|
||||
|
||||
// Positioning menu below input
|
||||
geocompleter.geocompleter('autocompleter', 'option', 'position', {
|
||||
of: geocompleter.closest('.input-table'),
|
||||
my: 'left top',
|
||||
at: 'left bottom'
|
||||
});
|
||||
|
||||
// On open menu calculate max-width
|
||||
geocompleter.geocompleter('autocompleter', 'on', 'autocompleteopen', function (event, ui) {
|
||||
$(this).autocomplete('widget').css('min-width', geocompleter.closest('.input-table').outerWidth());
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
export default regiser;
|
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// launch application
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import RegisterForm from './common/forms/views/form';
|
||||
|
||||
const registerProvider = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const initialize = () => {
|
||||
var fieldsConfiguration = [];
|
||||
|
||||
$.when.apply($, [
|
||||
$.ajax({
|
||||
url: '/login/registration-fields/',
|
||||
success: function (config) {
|
||||
fieldsConfiguration = config;
|
||||
}
|
||||
})
|
||||
]).done(function () {
|
||||
|
||||
var rules = [];
|
||||
var defaultRules = [
|
||||
{
|
||||
name: 'email',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
rules: 'valid_email',
|
||||
message: localeService.t('validation_email')
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
rules: 'min_length[5]',
|
||||
message: localeService.t('validation_length_min', {
|
||||
postProcess: 'sprintf',
|
||||
sprintf: ['5']
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'passwordConfirm',
|
||||
rules: 'matches[password]',
|
||||
message: localeService.t('password_match')
|
||||
},
|
||||
{
|
||||
name: 'accept-tou',
|
||||
rules: 'required',
|
||||
message: localeService.t('accept_tou'),
|
||||
type: 'checkbox'
|
||||
},
|
||||
{
|
||||
name: 'collections[]',
|
||||
rules: 'min_length[1]',
|
||||
message: localeService.t('validation_choice_min', {
|
||||
postProcess: 'sprintf',
|
||||
sprintf: ['1']
|
||||
}),
|
||||
type: 'multiple'
|
||||
}
|
||||
];
|
||||
|
||||
_.each(fieldsConfiguration, function (field) {
|
||||
if (field.required) {
|
||||
var rule = {
|
||||
name: field.name,
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
};
|
||||
|
||||
defaultRules.push(rule);
|
||||
}
|
||||
});
|
||||
|
||||
_.each(defaultRules, function (rule) {
|
||||
// add rule if element exists
|
||||
if ($('[name="' + rule.name + '"]').length >= 1) {
|
||||
rules.push(rule);
|
||||
}
|
||||
});
|
||||
|
||||
new RegisterForm({
|
||||
el: $('form[name=registerForm]'),
|
||||
rules: rules
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
export default registerProvider;
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import RenewEmailForm from './common/forms/views/form';
|
||||
|
||||
const renewEmail = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const initialize = () => {
|
||||
new RenewEmailForm({
|
||||
el: $('form[name=changeEmail]'),
|
||||
errorTemplate: '#field_errors_block',
|
||||
onRenderError: function (name, $el) {
|
||||
$el.closest('.control-group').addClass('error');
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
name: 'form_password',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'form_email',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'form_email',
|
||||
rules: 'email',
|
||||
message: localeService.t('validation_email')
|
||||
},
|
||||
{
|
||||
name: 'form_email_confirm',
|
||||
rules: 'matches[form_email]',
|
||||
message: localeService.t('email_match')
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
export default renewEmail;
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import RenewPasswordForm from './common/forms/views/formType/passwordSetter';
|
||||
|
||||
const renewPassword = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const initialize = () => {
|
||||
|
||||
require.ensure([], () => {
|
||||
services.zxcvbn = require('zxcvbn');
|
||||
new RenewPasswordForm({
|
||||
services,
|
||||
el: $('form[name=passwordRenewForm]'),
|
||||
rules: [
|
||||
{
|
||||
name: 'password[password]',
|
||||
rules: 'required',
|
||||
message: localeService.t('validation_blank')
|
||||
},
|
||||
{
|
||||
name: 'password[password]',
|
||||
rules: 'min_length[5]',
|
||||
message: localeService.t('validation_length_min', {
|
||||
postProcess: 'sprintf',
|
||||
sprintf: ['5']
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'password[confirm]',
|
||||
rules: 'matches[password[password]]',
|
||||
message: localeService.t('password_match')
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
export default renewPassword;
|
@@ -0,0 +1,55 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
const archiveBasket = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let $container = null;
|
||||
const initialize = () => {
|
||||
$container = $('body');
|
||||
$container.on('click', '.basket-archive-action', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
doArchive($el.data('basket-id'));
|
||||
});
|
||||
};
|
||||
|
||||
function doArchive(basketId) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/baskets/${basketId}/archive/?archive=1`,
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
const basket = $('#SSTT_' + basketId);
|
||||
const next = basket.next();
|
||||
|
||||
if (next.data('ui-droppable')) {
|
||||
next.droppable('destroy');
|
||||
}
|
||||
|
||||
next.slideUp().remove();
|
||||
|
||||
if (basket.data('ui-droppable')) {
|
||||
basket.droppable('destroy');
|
||||
}
|
||||
|
||||
basket.slideUp().remove();
|
||||
|
||||
if ($('#baskets .SSTT').length === 0) {
|
||||
appEvents.emit('workzone.refresh');
|
||||
}
|
||||
} else {
|
||||
alert(data.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
|
||||
export default archiveBasket;
|
276
Phraseanet-production-client/src/components/basket/browse.js
Normal file
276
Phraseanet-production-client/src/components/basket/browse.js
Normal file
@@ -0,0 +1,276 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
require('./../../phraseanet-common/components/tooltip');
|
||||
import merge from 'lodash.merge';
|
||||
const humane = require('humane-js');
|
||||
|
||||
const basketBrowse = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const initialize = () => {
|
||||
$('body').on('click', '.basket-browse-action', (event) => {
|
||||
event.preventDefault();
|
||||
const $el = $(event.currentTarget);
|
||||
let dialogOptions = {};
|
||||
|
||||
if ($el.attr('title') !== undefined) {
|
||||
dialogOptions.title = $el.attr('title');
|
||||
dialogOptions.width = 920;
|
||||
}
|
||||
|
||||
openModal(dialogOptions);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const openModal = (options = {}) => {
|
||||
|
||||
let dialogOptions = merge({
|
||||
size: 'Medium',
|
||||
loading: false
|
||||
}, options);
|
||||
const $dialog = dialog.create(services, dialogOptions);
|
||||
|
||||
return $.get(`${url}prod/WorkZone/Browse/`, function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onDialogReady();
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
const _onDialogReady = () => {
|
||||
const $container = $('#BasketBrowser');
|
||||
let results = null;
|
||||
|
||||
function loadResults(datas, url) {
|
||||
let $results = $('.results', $container);
|
||||
results = $.ajax({
|
||||
type: 'GET',
|
||||
url: url,
|
||||
dataType: 'html',
|
||||
data: datas,
|
||||
beforeSend: function () {
|
||||
if (results && results.abort && typeof results.abort === 'function') {
|
||||
results.abort();
|
||||
}
|
||||
$results.addClass('loading').empty();
|
||||
},
|
||||
error: function () {
|
||||
$results.removeClass('loading');
|
||||
},
|
||||
timeout: function () {
|
||||
$results.removeClass('loading');
|
||||
},
|
||||
success: function (data) {
|
||||
$results.removeClass('loading').append(data);
|
||||
activateLinks($results);
|
||||
active_archiver($results);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function loadBasket(url) {
|
||||
results = $.ajax({
|
||||
type: 'GET',
|
||||
url,
|
||||
dataType: 'html',
|
||||
beforeSend: function () {
|
||||
if (results && results.abort && typeof results.abort === 'function') {
|
||||
results.abort();
|
||||
}
|
||||
$('.Browser', $container).hide();
|
||||
$('.Basket', $container).addClass('loading').empty().show();
|
||||
},
|
||||
error: function () {
|
||||
$('.Browser', $container).show();
|
||||
$('.Basket', $container).removeClass('loading').hide();
|
||||
},
|
||||
timeout: function () {
|
||||
$('.Browser', $container).show();
|
||||
$('.Basket', $container).removeClass('loading').hide();
|
||||
},
|
||||
success: function (data) {
|
||||
$('.Basket', $container).removeClass('loading').append(data);
|
||||
|
||||
$('.Basket a.back', $container).bind('click', function () {
|
||||
$('.Basket', $container).hide();
|
||||
$('.Browser', $container).show();
|
||||
|
||||
return false;
|
||||
});
|
||||
active_archiver($('.Basket', $container));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function activateLinks($scope) {
|
||||
let confirmBox = {};
|
||||
let buttons = {};
|
||||
|
||||
$('a.result', $scope).bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
var $this = $(this);
|
||||
|
||||
loadResults({}, $this.attr('href'));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.result_page').bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
var $this = $(this);
|
||||
|
||||
loadResults({}, $this.attr('href'));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('a.basket_link', $scope).bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
var $this = $(this);
|
||||
|
||||
loadBasket($this.attr('href'));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('a.delete-basket', $scope).bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
var $this = $(this);
|
||||
var buttons = {};
|
||||
|
||||
buttons[localeService.t('valider')] = function () {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
url: $this.attr('href'),
|
||||
data: {},
|
||||
success: function (datas) {
|
||||
if (datas.success) {
|
||||
confirmBox.close();
|
||||
$('form[name="BasketBrowser"]', $container).trigger('submit');
|
||||
appEvents.emit('workzone.refresh');
|
||||
} else {
|
||||
confirmBox.close();
|
||||
var alertBox = dialog.create(services, {
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true
|
||||
}, 2);
|
||||
|
||||
alertBox.setContent(datas.message);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
confirmBox.close();
|
||||
var alertBox = dialog.create(services, {
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true
|
||||
}, 2);
|
||||
|
||||
alertBox.setContent("{{'Something wrong happened, please retry or contact an admin.'|trans|e('js') }}");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
confirmBox = dialog.create(services, {
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
cancelButton: true,
|
||||
buttons: buttons
|
||||
}, 2);
|
||||
|
||||
confirmBox.setContent("{{'You are about to delete this basket. Would you like to continue ?'|trans|e('js') }}");
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function active_archiver($scope) {
|
||||
$('a.UserTips', $scope).bind('click', function () {
|
||||
|
||||
return false;
|
||||
}).tooltip();
|
||||
|
||||
$('.infoTips, .previewTips', $scope).tooltip();
|
||||
|
||||
$('a.archive_toggler', $scope).bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
const $this = $(this);
|
||||
const parent = $this.parent();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: $this.attr('href'),
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
$('.loader', parent).show();
|
||||
$('.archive_toggler:visible', parent).addClass('last_act').hide();
|
||||
},
|
||||
error: function () {
|
||||
$('.loader', parent).hide();
|
||||
$('.last_act', parent).removeClass('last_act').show();
|
||||
},
|
||||
timeout: function () {
|
||||
$('.loader', parent).hide();
|
||||
$('.last_act', parent).removeClass('last_act').show();
|
||||
},
|
||||
success: function (data) {
|
||||
$('.loader', parent).hide();
|
||||
$('.last_act', parent).removeClass('last_act');
|
||||
if (!data.success) {
|
||||
humane.error(data.message);
|
||||
|
||||
return;
|
||||
}
|
||||
if (data.archive === true) {
|
||||
$('.unarchiver', parent).show();
|
||||
$('.archiver', parent).hide();
|
||||
$($this).closest('.result').removeClass('unarchived');
|
||||
} else {
|
||||
$('.unarchiver', parent).hide();
|
||||
$('.archiver', parent).show();
|
||||
$($this).closest('.result').addClass('unarchived');
|
||||
}
|
||||
|
||||
appEvents.emit('workzone.refresh');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
$('form[name="BasketBrowser"]', $container).bind('submit', function () {
|
||||
|
||||
let $this = $(this);
|
||||
|
||||
loadResults($this.serializeArray(), $this.attr('action'));
|
||||
|
||||
return false;
|
||||
}).trigger('submit').find('label').bind('click', function () {
|
||||
const input = $(this).prev('input');
|
||||
let inputs = $('input[name="' + $(this).prev('input').attr('name') + '"]', $container);
|
||||
inputs.prop('checked', false).next('label').removeClass('selected');
|
||||
|
||||
input.prop('checked', true).next('label').addClass('selected');
|
||||
$('form[name="BasketBrowser"]', $container).trigger('submit');
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
|
||||
export default basketBrowse;
|
101
Phraseanet-production-client/src/components/basket/create.js
Normal file
101
Phraseanet-production-client/src/components/basket/create.js
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* triggered via workzone > Basket > context menu
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import merge from 'lodash.merge';
|
||||
const basketCreate = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let searchSelectionSerialized = '';
|
||||
appEvents.listenAll({
|
||||
'broadcast.searchResultSelection': (selection) => {
|
||||
searchSelectionSerialized = selection.serialized;
|
||||
}
|
||||
});
|
||||
|
||||
const initialize = () => {
|
||||
$('body').on('click', '.basket-create-action', (event) => {
|
||||
event.preventDefault();
|
||||
const $el = $(event.currentTarget);
|
||||
let dialogOptions = {};
|
||||
|
||||
if ($el.attr('title') !== undefined) {
|
||||
dialogOptions.title = $el.attr('title');
|
||||
}
|
||||
|
||||
openModal(dialogOptions);
|
||||
});
|
||||
};
|
||||
|
||||
const openModal = (options = {}) => {
|
||||
|
||||
let dialogOptions = merge({
|
||||
size: 'Small',
|
||||
loading: false
|
||||
}, options);
|
||||
const $dialog = dialog.create(services, dialogOptions);
|
||||
|
||||
return $.get(`${url}prod/baskets/create/`, function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onDialogReady();
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
const _onDialogReady = () => {
|
||||
// recordBridge(services).initialize();
|
||||
var $dialog = dialog.get(1);
|
||||
var $dialogBox = $dialog.getDomElement();
|
||||
|
||||
$('input[name="lst"]', $dialogBox).val(searchSelectionSerialized);
|
||||
|
||||
var buttons = $dialog.getOption('buttons');
|
||||
|
||||
buttons[localeService.t('create')] = function () {
|
||||
$('form', $dialogBox).trigger('submit');
|
||||
};
|
||||
|
||||
$dialog.setOption('buttons', buttons);
|
||||
|
||||
$('form', $dialogBox).bind('submit', function (event) {
|
||||
|
||||
var $form = $(this);
|
||||
var $dialog = $dialogBox.closest('.ui-dialog');
|
||||
var buttonPanel = $dialog.find('.ui-dialog-buttonpane');
|
||||
|
||||
// @TODO should be in a service:
|
||||
$.ajax({
|
||||
type: $form.attr('method'),
|
||||
url: $form.attr('action'),
|
||||
data: $form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
$(":button:contains('" + localeService.t('create') + "')", buttonPanel)
|
||||
.attr('disabled', true).addClass('ui-state-disabled');
|
||||
},
|
||||
success: function (data) {
|
||||
appEvents.emit('workzone.refresh', {
|
||||
basketId: data.basket.id
|
||||
});
|
||||
dialog.close(1);
|
||||
|
||||
return;
|
||||
},
|
||||
error: function () {
|
||||
$(":button:contains('" + localeService.t('create ') + "')", buttonPanel)
|
||||
.attr('disabled', false).removeClass('ui-state-disabled');
|
||||
},
|
||||
timeout: function () {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
|
||||
export default basketCreate;
|
122
Phraseanet-production-client/src/components/basket/delete.js
Normal file
122
Phraseanet-production-client/src/components/basket/delete.js
Normal file
@@ -0,0 +1,122 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
|
||||
const deleteBasket = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let $container = null;
|
||||
const initialize = () => {
|
||||
$container = $('body');
|
||||
$container.on('click', '.basket-delete-action', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
deleteConfirmation($el, $el.data('context'));
|
||||
});
|
||||
};
|
||||
|
||||
const deleteConfirmation = ($el, type) => {
|
||||
switch (type) {
|
||||
/*case 'IMGT':
|
||||
case 'CHIM':
|
||||
|
||||
var lst = '';
|
||||
|
||||
if (type === 'IMGT') {
|
||||
lst = p4.Results.Selection.serialize();
|
||||
}
|
||||
if (type === 'CHIM') {
|
||||
lst = p4.WorkZone.Selection.serialize();
|
||||
}
|
||||
|
||||
_deleteRecords(lst);
|
||||
break;
|
||||
*/
|
||||
case 'SSTT':
|
||||
|
||||
var buttons = {};
|
||||
buttons[localeService.t('valider')] = function (e) {
|
||||
_deleteBasket($el);
|
||||
};
|
||||
|
||||
$('#DIALOG').empty().append(localeService.t('confirmDel')).attr('title', localeService.t('attention')).dialog({
|
||||
autoOpen: false,
|
||||
resizable: false,
|
||||
modal: true,
|
||||
draggable: false
|
||||
}).dialog('open').dialog('option', 'buttons', buttons);
|
||||
$('#tooltip').hide();
|
||||
break;
|
||||
/*case 'STORY':
|
||||
lst = $el.val();
|
||||
_deleteRecords(lst);
|
||||
break;*/
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
const _deleteBasket = (item) => {
|
||||
if ($('#DIALOG').data('ui-dialog')) {
|
||||
$('#DIALOG').dialog('destroy');
|
||||
}
|
||||
// id de chutier
|
||||
var k = $(item).attr('id').split('_').slice(1, 2).pop();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/baskets/${k}/delete/`,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
var basket = $('#SSTT_' + k);
|
||||
var next = basket.next();
|
||||
|
||||
if (next.data('ui-droppable')) {
|
||||
next.droppable('destroy');
|
||||
}
|
||||
|
||||
next.slideUp().remove();
|
||||
|
||||
if (basket.data('ui-droppable')) {
|
||||
basket.droppable('destroy');
|
||||
}
|
||||
|
||||
basket.slideUp().remove();
|
||||
|
||||
if ($('#baskets .SSTT').length === 0) {
|
||||
appEvents.emit('workzone.refresh');
|
||||
}
|
||||
} else {
|
||||
alert(data.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*const _deleteRecords = (lst) => {
|
||||
if (lst.split(';').length === 0) {
|
||||
alert(localeService.t('nodocselected'));
|
||||
return false;
|
||||
}
|
||||
let $dialog = dialog.create(services, {
|
||||
size: 'Small',
|
||||
title: localeService.t('deleteRecords')
|
||||
});
|
||||
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '../prod/records/delete/what/',
|
||||
dataType: 'html',
|
||||
data: {lst: lst},
|
||||
success: function (data) {
|
||||
$dialog.setContent(data);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
};*/
|
||||
|
||||
return {initialize, deleteConfirmation};
|
||||
};
|
||||
|
||||
export default deleteBasket;
|
40
Phraseanet-production-client/src/components/basket/index.js
Normal file
40
Phraseanet-production-client/src/components/basket/index.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import $ from 'jquery';
|
||||
import ui from '../ui';
|
||||
import notify from '../notify';
|
||||
|
||||
const basket = () => {
|
||||
|
||||
const onUpdatedContent = (data) => {
|
||||
|
||||
if (data.changed.length > 0) {
|
||||
let current_open = $('.SSTT.ui-state-active');
|
||||
let main_open = false;
|
||||
for (let i = 0; i !== data.changed.length; i++) {
|
||||
var sstt = $('#SSTT_' + data.changed[i]);
|
||||
if (sstt.size() === 0) {
|
||||
if (main_open === false) {
|
||||
$('#baskets .bloc').animate({top: 30}, function () {
|
||||
$('#baskets .alert_datas_changed:first').show();
|
||||
});
|
||||
main_open = true;
|
||||
}
|
||||
} else {
|
||||
if (!sstt.hasClass('active')) {
|
||||
sstt.addClass('unread');
|
||||
} else {
|
||||
$('.alert_datas_changed', $('#SSTT_content_' + data.changed[i])).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const subscribeToEvents = {
|
||||
'notification.refresh': onUpdatedContent
|
||||
};
|
||||
|
||||
return {subscribeToEvents};
|
||||
};
|
||||
|
||||
export default basket;
|
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* triggered via workzone > Basket > context menu
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
import * as _ from 'underscore';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import Selectable from '../utils/selectable';
|
||||
import merge from 'lodash.merge';
|
||||
const basketReorderContent = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let searchSelectionSerialized = '';
|
||||
appEvents.listenAll({
|
||||
'broadcast.searchResultSelection': (selection) => {
|
||||
searchSelectionSerialized = selection.serialized;
|
||||
}
|
||||
});
|
||||
|
||||
const initialize = () => {
|
||||
$('body').on('click', '.basket-reorder-content-action', (event) => {
|
||||
event.preventDefault();
|
||||
const $el = $(event.currentTarget);
|
||||
let dialogOptions = {};
|
||||
|
||||
if ($el.attr('title') !== undefined) {
|
||||
dialogOptions.title = $el.attr('title');
|
||||
}
|
||||
|
||||
openModal($el.data('basket-id'), dialogOptions);
|
||||
});
|
||||
};
|
||||
|
||||
const openModal = (basketId, options = {}) => {
|
||||
|
||||
let dialogOptions = merge({
|
||||
size: 'Medium',
|
||||
loading: false
|
||||
}, options);
|
||||
const $dialog = dialog.create(services, dialogOptions);
|
||||
|
||||
return $.get(`${url}prod/baskets/${basketId}/reorder/`, function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onDialogReady();
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
const _onDialogReady = () => {
|
||||
var container = $('#reorder_box');
|
||||
|
||||
$('button.autoorder', container).bind('click', function () {
|
||||
autoorder();
|
||||
return false;
|
||||
});
|
||||
$('button.reverseorder', container).bind('click', function () {
|
||||
reverse_order();
|
||||
return false;
|
||||
});
|
||||
|
||||
function autoorder() {
|
||||
var val = $.trim($('#auto_order').val());
|
||||
|
||||
if (val === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
var diapos = [];
|
||||
$('#reorder_box .diapo form').each(function (i, n) {
|
||||
diapos.push({
|
||||
title: $('input[name=title]', n).val(),
|
||||
order: parseInt($('input[name=default]', n).val(), 10),
|
||||
id: $('input[name=id]', n).val(),
|
||||
date_created: new Date($('input[name=date_created]', n).val()),
|
||||
date_updated: new Date($('input[name=date_updated]', n).val()),
|
||||
});
|
||||
});
|
||||
|
||||
var elements = [];
|
||||
var sorterCallback;
|
||||
|
||||
if (val === 'default') {
|
||||
sorterCallback = function (diapo) {
|
||||
return diapo.order;
|
||||
};
|
||||
elements = sorting(sorterCallback, diapos, false);
|
||||
} else if(val === 'date_updated' || val === 'date_created'){
|
||||
sorterCallback = function(diapo) {
|
||||
if(val === 'date_created') {
|
||||
return diapo.date_created;
|
||||
}
|
||||
return diapo.date_updated;
|
||||
};
|
||||
elements = sorting(sorterCallback, diapos, true);
|
||||
} else {
|
||||
sorterCallback = function(diapo) {return diapo.title.toLowerCase();};
|
||||
elements = sorting(sorterCallback, diapos, false);
|
||||
}
|
||||
|
||||
$('#reorder_box .elements').append(elements);
|
||||
}
|
||||
|
||||
function sorting(sorterCallback, diapos, reverse) {
|
||||
var elements = [];
|
||||
if(reverse == true) {
|
||||
_.chain(diapos)
|
||||
.sortBy(sorterCallback)
|
||||
.reverse()
|
||||
.each(function(diapo) {
|
||||
elements.push($('#ORDER_'+ diapo.id));
|
||||
});
|
||||
}else {
|
||||
_.chain(diapos)
|
||||
.sortBy(sorterCallback)
|
||||
.each(function(diapo) {
|
||||
elements.push($('#ORDER_'+ diapo.id));
|
||||
});
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
function reverse_order() {
|
||||
var $container = $('#reorder_box .elements');
|
||||
$('#reorder_box .diapo').each(function () {
|
||||
$(this).prependTo($container);
|
||||
});
|
||||
}
|
||||
|
||||
('.elements div', container).bind('click', function(){
|
||||
$(this).addClass("selected").siblings().removeClass("selected");
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.elements', container).sortable({
|
||||
appendTo: container,
|
||||
placeholder: 'diapo ui-sortable-placeholder',
|
||||
distance: 20,
|
||||
cursorAt: {
|
||||
top: 10,
|
||||
left: -20
|
||||
},
|
||||
items: 'div.diapo',
|
||||
scroll: true,
|
||||
scrollSensitivity: 40,
|
||||
scrollSpeed: 30,
|
||||
start: function (event, ui) {
|
||||
var selected = $('.selected', container);
|
||||
|
||||
selected.each(function (i, n) {
|
||||
$(n).attr('position', i);
|
||||
});
|
||||
|
||||
var n = selected.length - 1;
|
||||
|
||||
$('.selected:visible', container).hide();
|
||||
|
||||
while (n > 0) {
|
||||
$('<div style="height:130px;" class="diapo ui-sortable-placeholderfollow"></div>').after($('.diapo.ui-sortable-placeholder', container));
|
||||
n--;
|
||||
}
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
|
||||
$('.diapo.ui-sortable-placeholderfollow', container).remove();
|
||||
|
||||
let main_id = $(ui.item[0]).attr('id');
|
||||
|
||||
let selected = $('.selected', container);
|
||||
let sorter = [];
|
||||
|
||||
|
||||
selected.each(function (i, n) {
|
||||
|
||||
var position = parseInt($(n).attr('position'), 10);
|
||||
|
||||
if (position !== '') {
|
||||
sorter[position] = $(n);
|
||||
}
|
||||
|
||||
var id = $(n).attr('id');
|
||||
if (id === main_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var before = true;
|
||||
var last_moved = $(ui.item[0]);
|
||||
$(sorter).each(function (i, n) {
|
||||
$(n).show().removeAttr('position');
|
||||
if ($(n).attr('id') === main_id) {
|
||||
before = false;
|
||||
} else {
|
||||
if (before) {
|
||||
$(n).before($(ui.item[0]));
|
||||
} else {
|
||||
$(n).after($(last_moved));
|
||||
}
|
||||
|
||||
}
|
||||
last_moved = sorter[i];
|
||||
});
|
||||
|
||||
},
|
||||
change: function () {
|
||||
$('.diapo.ui-sortable-placeholderfollow', container).remove();
|
||||
|
||||
var n = OrderSelection.length() - 1;
|
||||
while (n > 0) {
|
||||
$('<div style="height:130px;" class="diapo ui-sortable-placeholderfollow"></div>').after($('.diapo.ui-sortable-placeholder', container));
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
}).disableSelection();
|
||||
|
||||
var OrderSelection = new Selectable(services, $('.elements', container), {
|
||||
selector: '.CHIM'
|
||||
});
|
||||
|
||||
$('form[name="reorder"] .btn').bind('click', function (event) {
|
||||
|
||||
//$this.SetLoader(true);
|
||||
var $form =$(this).closest('form');
|
||||
|
||||
$('.elements form', container).each(function (i, el) {
|
||||
var id = $('input[name="id"]', $(el)).val();
|
||||
|
||||
$('input[name="element[' + id + ']"]', $form).val(i + 1);
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: $form.attr('method'),
|
||||
url: $form.attr('action'),
|
||||
data: $form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
|
||||
},
|
||||
success: function (data) {
|
||||
if (!data.success) {
|
||||
alert(data.message);
|
||||
}
|
||||
appEvents.emit('workzone.refresh', {
|
||||
basketId: 'current'
|
||||
});
|
||||
dialog.get(1).close();
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
|
||||
export default basketReorderContent;
|
91
Phraseanet-production-client/src/components/basket/update.js
Normal file
91
Phraseanet-production-client/src/components/basket/update.js
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* triggered via workzone > Basket > context menu
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import merge from 'lodash.merge';
|
||||
const humane = require('humane-js');
|
||||
|
||||
const basketUpdate = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let basketId = false;
|
||||
let searchSelectionSerialized = '';
|
||||
appEvents.listenAll({
|
||||
'broadcast.searchResultSelection': (selection) => {
|
||||
searchSelectionSerialized = selection.serialized;
|
||||
}
|
||||
});
|
||||
|
||||
const initialize = () => {
|
||||
$('body').on('click', '.basket-update-action', (event) => {
|
||||
event.preventDefault();
|
||||
const $el = $(event.currentTarget);
|
||||
let dialogOptions = {};
|
||||
|
||||
if ($el.attr('title') !== undefined) {
|
||||
dialogOptions.title = $el.attr('title');
|
||||
}
|
||||
basketId = $el.data('basket-id');
|
||||
openModal(dialogOptions);
|
||||
});
|
||||
};
|
||||
|
||||
const openModal = (options = {}) => {
|
||||
|
||||
let dialogOptions = merge({
|
||||
size: 'Medium',
|
||||
loading: false
|
||||
}, options);
|
||||
const $dialog = dialog.create(services, dialogOptions);
|
||||
|
||||
return $.get(`${url}prod/baskets/${basketId}/update/`, (data) => {
|
||||
$dialog.setContent(data);
|
||||
_onDialogReady();
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
const _onDialogReady = () => {
|
||||
$('form[name="basket-rename-box"]').on('submit', function (event) {
|
||||
event.preventDefault();
|
||||
onSubmitRenameForm(event);
|
||||
});
|
||||
|
||||
$('#basket-rename-box button').on('click', function (event) {
|
||||
event.preventDefault();
|
||||
onSubmitRenameForm(event);
|
||||
});
|
||||
|
||||
var onSubmitRenameForm = function (event) {
|
||||
var $form = $(event.currentTarget).closest('form');
|
||||
$.ajax({
|
||||
type: $form.attr('method'),
|
||||
url: $form.attr('action'),
|
||||
dataType: 'json',
|
||||
data: $form.serializeArray(),
|
||||
beforeSend: function () {
|
||||
|
||||
},
|
||||
success: function (data) {
|
||||
dialog.get(1).close();
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
appEvents.emit('workzone.refresh', {
|
||||
basketId: basketId
|
||||
});
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
return {initialize};
|
||||
};
|
||||
|
||||
export default basketUpdate;
|
62
Phraseanet-production-client/src/components/cgu/index.js
Normal file
62
Phraseanet-production-client/src/components/cgu/index.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import $ from 'jquery';
|
||||
import * as appCommons from './../../phraseanet-common';
|
||||
const humane = require('humane-js');
|
||||
const cgu = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const initialize = (options = {}) => {
|
||||
const { $container } = options;
|
||||
var $this = $('.cgu-dialog:first');
|
||||
$this.dialog({
|
||||
autoOpen: true,
|
||||
closeOnEscape: false,
|
||||
draggable: false,
|
||||
modal: true,
|
||||
resizable: false,
|
||||
width: 800,
|
||||
height: 500,
|
||||
open: function () {
|
||||
$this.parents('.ui-dialog:first').find('.ui-dialog-titlebar-close').remove();
|
||||
$('.cgus-accept', $(this)).bind('click', function () {
|
||||
acceptCgus($('.cgus-accept', $this).attr('id'), $('.cgus-accept', $this).attr('date'));
|
||||
$this.dialog('close').remove();
|
||||
initialize(services, options);
|
||||
});
|
||||
$('.cgus-cancel', $(this)).bind('click', function () {
|
||||
if (confirm(localeService.t('warningDenyCgus'))) {
|
||||
cancelCgus($('.cgus-cancel', $this).attr('id').split('_').pop());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function acceptCgus(name, value) {
|
||||
appCommons.userModule.setPref(name, value);
|
||||
}
|
||||
|
||||
function cancelCgus(id) {
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/TOU/deny/${id}/`,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
alert(localeService.t('cgusRelog'));
|
||||
self.location.replace(self.location.href);
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
initialize
|
||||
};
|
||||
};
|
||||
|
||||
export default cgu;
|
@@ -0,0 +1,91 @@
|
||||
let instance = null;
|
||||
import * as _ from 'underscore';
|
||||
|
||||
export default class ApplicationConfigService {
|
||||
configuration;
|
||||
|
||||
constructor(config) {
|
||||
// if( !instance ) {
|
||||
// instance = this;
|
||||
// }
|
||||
this.configuration = config;
|
||||
// return instance;
|
||||
}
|
||||
|
||||
get(configKey) {
|
||||
if (configKey !== undefined) {
|
||||
var foundValue = this._findKeyValue(configKey || this.configuration);
|
||||
switch (typeof foundValue) {
|
||||
case 'string':
|
||||
return foundValue;
|
||||
default:
|
||||
return foundValue ? foundValue : null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
set(configKey, value) {
|
||||
if (configKey !== undefined) {
|
||||
if (typeof this.configuration[configKey] === 'object') {
|
||||
// merge
|
||||
this.configuration[configKey] = _.extend({}, this.configuration[configKey], value);
|
||||
} else {
|
||||
this.configuration[configKey] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @TODO cast
|
||||
_findKeyValue(configName) {
|
||||
if (!configName) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let isStr = _.isString(configName);
|
||||
let name = isStr ? configName : configName.name;
|
||||
let path = configName.indexOf('.') > 0 ? true : false;
|
||||
|
||||
if (path) {
|
||||
return this._search(this.configuration, name);
|
||||
|
||||
}
|
||||
var state = this.configuration[name];
|
||||
if (state && (isStr || (!isStr && state === configName))) {
|
||||
return state;
|
||||
} else if (isStr) {
|
||||
return state;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// @TODO cast
|
||||
_search(obj, path) {
|
||||
if (_.isNumber(path)) {
|
||||
path = [path];
|
||||
}
|
||||
if (_.isEmpty(path)) {
|
||||
return obj;
|
||||
}
|
||||
if (_.isEmpty(obj)) {
|
||||
return null;
|
||||
}
|
||||
if (_.isString(path)) {
|
||||
return this._search(obj, path.split('.'));
|
||||
}
|
||||
|
||||
var currentPath = path[0];
|
||||
|
||||
if (path.length === 1) {
|
||||
if (obj[currentPath] === void 0) {
|
||||
return null;
|
||||
}
|
||||
return obj[currentPath];
|
||||
}
|
||||
|
||||
return this._search(obj[currentPath], path.slice(1));
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
import ApplicationConfigService from './applicationConfigService';
|
||||
|
||||
let instance = null;
|
||||
|
||||
class ConfigService extends ApplicationConfigService {
|
||||
constructor(configuration) {
|
||||
super(configuration);
|
||||
if (!instance) {
|
||||
|
||||
instance = this;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
export default ConfigService;
|
56
Phraseanet-production-client/src/components/core/emitter.js
Normal file
56
Phraseanet-production-client/src/components/core/emitter.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import * as Rx from 'rx';
|
||||
var hasOwnProp = {}.hasOwnProperty;
|
||||
|
||||
function createName(name) {
|
||||
return '$' + name;
|
||||
}
|
||||
|
||||
let Emitter = function () {
|
||||
this.subjects = {};
|
||||
};
|
||||
|
||||
Emitter.prototype.emit = function (name, data) {
|
||||
var fnName = createName(name);
|
||||
this.subjects[fnName] || (this.subjects[fnName] = new Rx.Subject());
|
||||
this.subjects[fnName].onNext(data);
|
||||
|
||||
return this.subjects[fnName];
|
||||
};
|
||||
|
||||
Emitter.prototype.listen = function (name, handler) {
|
||||
var fnName = createName(name);
|
||||
this.subjects[fnName] || (this.subjects[fnName] = new Rx.Subject());
|
||||
return this.subjects[fnName].subscribe(handler);
|
||||
};
|
||||
Emitter.prototype.listenAll = function (group, name, handler) {
|
||||
for (let prop in group) {
|
||||
var fnName = createName(prop);
|
||||
this.subjects[fnName] || (this.subjects[fnName] = new Rx.Subject());
|
||||
this.subjects[fnName].subscribe(group[prop]);
|
||||
}
|
||||
};
|
||||
|
||||
Emitter.prototype.disposeOf = function (startWith) {
|
||||
var search = new RegExp('^\\$' + startWith);
|
||||
var subjects = this.subjects;
|
||||
for (let prop in subjects) {
|
||||
if (hasOwnProp.call(subjects, prop)) {
|
||||
if (search.test(prop)) {
|
||||
subjects[prop].dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.subjects = {};
|
||||
};
|
||||
Emitter.prototype.dispose = function () {
|
||||
var subjects = this.subjects;
|
||||
for (let prop in subjects) {
|
||||
if (hasOwnProp.call(subjects, prop)) {
|
||||
subjects[prop].dispose();
|
||||
}
|
||||
}
|
||||
|
||||
this.subjects = {};
|
||||
};
|
||||
export default Emitter;
|
@@ -0,0 +1,155 @@
|
||||
import _ from 'underscore';
|
||||
/**
|
||||
* Set a provider
|
||||
*
|
||||
*/
|
||||
|
||||
const provider = (services) => {
|
||||
const {configService, localeService, eventEmitter} = services;
|
||||
let accessToken;
|
||||
let defaultPosition;
|
||||
let defaultZoom;
|
||||
let markerDefaultZoom;
|
||||
let activeProvider;
|
||||
let fieldPosition;
|
||||
let defaultMapProvider;
|
||||
let transitionOptions = Object.create(null);
|
||||
let mapLayers = [{name: 'streets', value: 'mapbox://styles/mapbox/streets-v9'}];
|
||||
const initialize = () => {
|
||||
let isValid = false;
|
||||
// select geocoding provider:
|
||||
let geocodingProviders = configService.get('geocodingProviders');
|
||||
_.each(geocodingProviders, (provider) => {
|
||||
if (provider.enabled === true) {
|
||||
activeProvider = provider;
|
||||
accessToken = provider['public-key'];
|
||||
let fieldMapping = provider['position-fields'] !== undefined ? provider['position-fields'] : [];
|
||||
|
||||
fieldPosition = {};
|
||||
|
||||
if (fieldMapping.length > 0) {
|
||||
_.each(fieldMapping, (mapping) => {
|
||||
// latitude and longitude are combined in a composite field
|
||||
if (mapping.type === 'latlng') {
|
||||
fieldPosition = {
|
||||
latitude: (poi) => extractFromPosition('lat', poi[mapping.name]),
|
||||
longitude: (poi) => extractFromPosition('lon', poi[mapping.name])
|
||||
};
|
||||
} else if (mapping.type === 'lat') {
|
||||
// if latitude field mapping is provided, fallback:
|
||||
fieldPosition.latitude = (poi) => isNaN(parseFloat(poi[mapping.name], 10)) ? false : parseFloat(poi[mapping.name], 10);
|
||||
} else if (mapping.type === 'lon') {
|
||||
// if longitude field mapping is provided, fallback:
|
||||
fieldPosition.longitude = (poi) => isNaN(parseFloat(poi[mapping.name], 10)) ? false : parseFloat(poi[mapping.name], 10);
|
||||
}
|
||||
});
|
||||
if (fieldPosition.latitude !== undefined && fieldPosition.longitude !== undefined) {
|
||||
isValid = true;
|
||||
}
|
||||
} else {
|
||||
fieldPosition = {
|
||||
latitude: (poi) => getCoordinatesFromTechnicalInfo(poi, 'lat'),
|
||||
longitude: (poi) => getCoordinatesFromTechnicalInfo(poi, 'lng')
|
||||
};
|
||||
isValid = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// set default values:
|
||||
|
||||
|
||||
var defaultPositionValue = $('#map-position-from-setting').val();
|
||||
if(defaultPositionValue != '') {
|
||||
defaultPositionValue = defaultPositionValue.split('"');
|
||||
var arr = [];
|
||||
arr.push(defaultPositionValue[1]);
|
||||
arr.push(defaultPositionValue[3]);
|
||||
defaultPosition = arr ;
|
||||
} else {
|
||||
defaultPosition = provider['default-position'];
|
||||
}
|
||||
|
||||
|
||||
defaultZoom = $('#map-zoom-from-setting').val()!='' ? $('#map-zoom-from-setting').val() : provider['default-zoom'] || 2;
|
||||
markerDefaultZoom = provider['marker-default-zoom'] || 12;
|
||||
defaultMapProvider = provider['map-provider'] || "mapboxWebGL";
|
||||
if (provider['map-layers'] && provider['map-layers'].length > 0) {
|
||||
//update map layer;
|
||||
mapLayers = provider['map-layers'];
|
||||
}
|
||||
if (provider['transition-mapboxgl'] !== undefined) {
|
||||
var options = provider['transition-mapboxgl'][0] || [];
|
||||
transitionOptions.animate = options['animate'] !== undefined ? options['animate'] : true;
|
||||
transitionOptions.speed = options['speed'] || 1.2;
|
||||
transitionOptions.curve = options['curve'] || 1.42;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (accessToken === undefined) {
|
||||
isValid = false;
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
const getCoordinatesFromTechnicalInfo = (poi, fieldMapping) => {
|
||||
if (poi["technicalInfo"] !== undefined) {
|
||||
if (fieldMapping == 'lat') {
|
||||
return isNaN(parseFloat(poi["technicalInfo"].latitude, 10)) ? false : parseFloat(poi["technicalInfo"].latitude, 10)
|
||||
} else {
|
||||
return isNaN(parseFloat(poi["technicalInfo"].longitude, 10)) ? false : parseFloat(poi["technicalInfo"].longitude, 10)
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract latitude or longitude from a position
|
||||
* @param name
|
||||
* @param source
|
||||
* @returns {*}
|
||||
*/
|
||||
const extractFromPosition = (name, source) => {
|
||||
if (source === undefined || source === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let position = source.split(' ');
|
||||
|
||||
if (position.length !== 2) {
|
||||
position = source.split(',');
|
||||
}
|
||||
|
||||
// ok parse lat
|
||||
if (position.length === 2) {
|
||||
if (name === 'lat' || name === 'latitude') {
|
||||
return parseFloat(position[0])
|
||||
}
|
||||
return parseFloat(position[1])
|
||||
} else {
|
||||
// invalid
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const getConfiguration = () => {
|
||||
return {
|
||||
defaultPosition,
|
||||
defaultZoom,
|
||||
markerDefaultZoom,
|
||||
fieldPosition,
|
||||
accessToken,
|
||||
defaultMapProvider,
|
||||
mapLayers,
|
||||
provider: activeProvider,
|
||||
transitionOptions
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
initialize, getConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
export default provider;
|
@@ -0,0 +1,97 @@
|
||||
const leafletLocaleFr = {
|
||||
draw: {
|
||||
toolbar: {
|
||||
actions: {
|
||||
title: 'Annulez le dessin',
|
||||
text: 'Annuler'
|
||||
},
|
||||
finish: {
|
||||
title: 'Terminer le dessin',
|
||||
text: 'Terminer'
|
||||
},
|
||||
undo: {
|
||||
title: 'Supprimer le dernier point',
|
||||
text: 'Supprimer le dernier point'
|
||||
},
|
||||
buttons: {
|
||||
polyline: 'Dessiner une polyligne',
|
||||
polygon: 'Dessiner un polygone',
|
||||
rectangle: 'Dessiner un rectangle',
|
||||
circle: 'Dessiner un cercle',
|
||||
marker: 'Dessiner un marqueur'
|
||||
}
|
||||
},
|
||||
handlers: {
|
||||
circle: {
|
||||
tooltip: {
|
||||
start: 'Cliquez et déplacez pour dessiner un cercle.'
|
||||
}
|
||||
},
|
||||
marker: {
|
||||
tooltip: {
|
||||
start: 'Cliquez sur la carte pour placer un marqueur.'
|
||||
}
|
||||
},
|
||||
polygon: {
|
||||
tooltip: {
|
||||
start: 'Cliquez pour commencer à dessiner une forme.',
|
||||
cont: 'Cliquez pour continuer à dessiner une forme.',
|
||||
end: 'Cliquez sur le dernier point pour fermer cette forme.'
|
||||
}
|
||||
},
|
||||
polyline: {
|
||||
error: '<strong>Erreur:</strong> Les arrêtes de la forme ne doivent pas se croiser!',
|
||||
tooltip: {
|
||||
start: 'Cliquez pour commencer à dessiner d\'une ligne.',
|
||||
cont: 'Cliquez pour continuer à dessiner une ligne.',
|
||||
end: 'Cliquez sur le dernier point pour terminer la ligne.'
|
||||
}
|
||||
},
|
||||
rectangle: {
|
||||
tooltip: {
|
||||
start: 'Cliquez et déplacez pour dessiner un rectangle.'
|
||||
}
|
||||
},
|
||||
simpleshape: {
|
||||
tooltip: {
|
||||
end: 'Relachez la souris pour finir de dessiner.'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
edit: {
|
||||
toolbar: {
|
||||
actions: {
|
||||
save: {
|
||||
title: 'Sauvegardez les changements.',
|
||||
text: 'Sauver'
|
||||
},
|
||||
cancel: {
|
||||
title: 'Annulez l\'édition, ignorer tous les changements.',
|
||||
text: 'Annuler'
|
||||
}
|
||||
},
|
||||
buttons: {
|
||||
edit: 'Editer les couches.',
|
||||
editDisabled: 'Pas de couches à éditer.',
|
||||
remove: 'Supprimer les couches.',
|
||||
removeDisabled: 'Pas de couches à supprimer.'
|
||||
}
|
||||
},
|
||||
handlers: {
|
||||
edit: {
|
||||
tooltip: {
|
||||
text: 'Déplacez les ancres, ou le marqueur pour éditer l\'objet.',
|
||||
subtext: 'Cliquez sur Annuler pour revenir sur les changements.'
|
||||
}
|
||||
},
|
||||
remove: {
|
||||
tooltip: {
|
||||
text: 'Cliquez sur l\'objet à enlever'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default leafletLocaleFr;
|
@@ -0,0 +1,279 @@
|
||||
.ui-widget-content .leaflet-popup-content {
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.mapbox-logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.phrasea-popup .leaflet-popup-content-wrapper {
|
||||
background: #3b3b3b;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.phrasea-popup .leaflet-popup-content-wrapper a {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.phrasea-popup .leaflet-popup-tip-container {
|
||||
width: 30px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.phrasea-popup .leaflet-popup-content p {
|
||||
color: #FFF;
|
||||
|
||||
}
|
||||
|
||||
.phrasea-popup .leaflet-popup-content p.help {
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.phrasea-popup .leaflet-popup-tip {
|
||||
border-top: 10px solid #3b3b3b;
|
||||
}
|
||||
|
||||
.updated-position {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ui-widget-content .leaflet-container {
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.ui-widget-content .leaflet-container label {
|
||||
color: #555555;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.ui-widget-content .leaflet-container form {
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
.ui-widget-content .leaflet-container input[type="radio"] {
|
||||
margin: -4px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.leaflet-control-mapbox-geocoder .leaflet-control-mapbox-geocoder-form input {
|
||||
box-shadow: none;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ui-widget-content .leaflet-container form {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-content {
|
||||
background: #555555;
|
||||
width: 200px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-anchor-top .mapboxgl-popup-tip {
|
||||
border-bottom-color: #555555;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip {
|
||||
border-bottom-color: #555555;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip {
|
||||
|
||||
border-bottom-color: #555555;
|
||||
}
|
||||
.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip {
|
||||
|
||||
border-top-color: #555555;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip {
|
||||
|
||||
border-top-color: #555555;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip {
|
||||
|
||||
border-top-color: #555555;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-anchor-left .mapboxgl-popup-tip {
|
||||
|
||||
border-right-color: #555555;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-anchor-right .mapboxgl-popup-tip {
|
||||
|
||||
border-left-color: #555555;
|
||||
}
|
||||
|
||||
.map-selection-container {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
top: 130px;
|
||||
right: 10px;
|
||||
border-radius: 5px;
|
||||
border: 2px solid #ccc;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.map-selection-container:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.map-dropdown-content {
|
||||
display: none;
|
||||
min-width: 80px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
background: #FFF;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.map-dropdown-content label {
|
||||
color: #555555;
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.map-drop-btn {
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.map-drop-btn i {
|
||||
padding: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.circle-control-container {
|
||||
position: absolute;
|
||||
top: 170px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
#map-notice-btn {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 6px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#map-notice-btn:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
#notice-box {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 6px;
|
||||
width: 305px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
|
||||
background-color: #ffffff;
|
||||
border: solid 1px #8f8f8f;
|
||||
padding: 4px 5px 5px 6px;
|
||||
}
|
||||
|
||||
.notice-header {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
font-family: Roboto;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0px;
|
||||
color: #3e3d3d;
|
||||
margin-left: 6px;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.notice-desc {
|
||||
display: block;
|
||||
font-family: Roboto;
|
||||
font-size: 12px;
|
||||
line-height: 1.17;
|
||||
letter-spacing: 0px;
|
||||
color: #3e3d3d;
|
||||
margin: 6px 10px 0px 10px;
|
||||
}
|
||||
|
||||
.notice-close-btn {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 2px;
|
||||
font-family: Roboto;
|
||||
font-size: 16px;
|
||||
color: #3e3d3d;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.draw-icon {
|
||||
margin-bottom: 5px;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
border-radius: 5px;
|
||||
border: 2px solid #ccc;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.draw-icon:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.draw-icon.selected {
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
.draw-icon i {
|
||||
font-size: 20px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.map-dropdown-content label input[type="radio"] {
|
||||
margin: 0px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.map-dropdown-content.show {
|
||||
display: block;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
const markerCollection = (services) => {
|
||||
const {configService, localeService, eventEmitter} = services;
|
||||
let markerCollection = {};
|
||||
let cachedGeoJson;
|
||||
let featureLayer;
|
||||
let map;
|
||||
let geoJsonPoiCollection;
|
||||
let editable;
|
||||
|
||||
const initialize = (params) => {
|
||||
let initWith = {map, featureLayer, geoJsonPoiCollection} = params;
|
||||
editable = params.editable || false;
|
||||
setCollection(geoJsonPoiCollection)
|
||||
};
|
||||
|
||||
const setCollection = (geoJsonPoiCollection) => {
|
||||
featureLayer.setGeoJSON(geoJsonPoiCollection);
|
||||
cachedGeoJson = featureLayer.getGeoJSON();
|
||||
featureLayer.eachLayer(function (layer) {
|
||||
setMarkerPopup(layer);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const triggerRefresh = () => {
|
||||
setCollection(cachedGeoJson);
|
||||
cachedGeoJson = featureLayer.getGeoJSON();
|
||||
};
|
||||
|
||||
const setMarkerPopup = (marker) => {
|
||||
switch (marker.feature.geometry.type) {
|
||||
case 'Polygon':
|
||||
break;
|
||||
case 'Point':
|
||||
setPoint(marker);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
const setPoint = (marker) => {
|
||||
markerCollection[marker._leaflet_id] = marker;
|
||||
let $content = $('<div style="min-width: 200px"/>');
|
||||
|
||||
let template = `<p>${marker.feature.properties.title}</p> `;
|
||||
|
||||
if (editable === true && marker.dragging !== undefined) {
|
||||
template += `
|
||||
<div class="view-mode">
|
||||
<button class="edit-position btn btn-inverse btn-small btn-block" data-marker-id="${marker._leaflet_id}">${localeService.t('mapMarkerEdit')}</button>
|
||||
</div>
|
||||
<div class="edit-mode">
|
||||
<p class="help">${localeService.t('mapMarkerMoveLabel')}</p>
|
||||
<p><span class="updated-position"></span></p>
|
||||
<div>
|
||||
<button class="cancel-position btn btn-inverse btn-small btn-block" data-marker-id="${marker._leaflet_id}">${localeService.t('mapMarkerEditCancel')}</button>
|
||||
<button class="submit-position btn btn-inverse btn-small btn-block" data-marker-id="${marker._leaflet_id}">${localeService.t('mapMarkerEditSubmit')}</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
$content.append(template);
|
||||
|
||||
$content.find('.edit-mode').hide();
|
||||
|
||||
$content.on('click', '.edit-position', (event) => {
|
||||
let $el = $(event.currentTarget);
|
||||
let marker = getMarker($el.data('marker-id'));
|
||||
marker._originalPosition = marker.getLatLng().wrap();
|
||||
marker.dragging.enable();
|
||||
$content.find('.view-mode').hide();
|
||||
$content.find('.edit-mode').show();
|
||||
$content.find('.help').show();
|
||||
});
|
||||
|
||||
$content.on('click', '.submit-position', (event) => {
|
||||
let $el = $(event.currentTarget);
|
||||
let marker = getMarker($el.data('marker-id'));
|
||||
|
||||
marker.dragging.disable();
|
||||
$content.find('.view-mode').show();
|
||||
$content.find('.help').hide();
|
||||
$content.find('.edit-mode').hide();
|
||||
marker._originalPosition = marker.getLatLng().wrap();
|
||||
eventEmitter.emit('markerChange', {marker, position: marker.getLatLng().wrap()});
|
||||
});
|
||||
|
||||
|
||||
$content.on('click', '.cancel-position', (event) => {
|
||||
let $el = $(event.currentTarget);
|
||||
let marker = getMarker($el.data('marker-id'));
|
||||
marker.dragging.disable();
|
||||
$content.find('.view-mode').show();
|
||||
|
||||
marker.setLatLng(marker._originalPosition);
|
||||
triggerRefresh();
|
||||
});
|
||||
|
||||
marker.bindPopup($content.get(0));
|
||||
|
||||
marker.on('dragend', () => {
|
||||
let position = marker.getLatLng().wrap();
|
||||
$content.find('.updated-position').html(`${position.lat}<br>${position.lng}`);
|
||||
$content.find('.edit-mode').show();
|
||||
marker.bindPopup($content.get(0));
|
||||
marker.openPopup();
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const getMarker = (markerId) => {
|
||||
return markerCollection[markerId];
|
||||
}
|
||||
|
||||
return {
|
||||
initialize, setCollection
|
||||
}
|
||||
}
|
||||
|
||||
export default markerCollection;
|
@@ -0,0 +1,231 @@
|
||||
import $ from 'jquery';
|
||||
let mapboxgl = require('mapbox-gl');
|
||||
|
||||
const markerGLCollection = (services) => {
|
||||
const {configService, localeService, eventEmitter} = services;
|
||||
let markerCollection = {};
|
||||
let cachedGeoJson;
|
||||
let map;
|
||||
let geojson;
|
||||
let editable;
|
||||
let isDraggable = false;
|
||||
let isCursorOverPoint = false;
|
||||
let isDragging = false;
|
||||
let popup = {};
|
||||
let popupDialog;
|
||||
|
||||
const initialize = (params) => {
|
||||
let initWith = {map, geojson} = params;
|
||||
editable = params.editable || false;
|
||||
setCollection(geojson)
|
||||
};
|
||||
|
||||
const setCollection = (geojson) => {
|
||||
cachedGeoJson = geojson;
|
||||
geojson.features.forEach(function (marker) {
|
||||
setMarkerPopup(marker);
|
||||
});
|
||||
};
|
||||
|
||||
const setMarkerPopup = (marker) => {
|
||||
switch (marker.geometry.type) {
|
||||
case 'Polygon':
|
||||
break;
|
||||
case 'Point':
|
||||
setPoint(marker);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
const setPoint = (marker) => {
|
||||
let $content = $('<div style="min-width: 200px"/>');
|
||||
|
||||
let template = `<p>${marker.properties.title}</p> `;
|
||||
|
||||
if (editable === true) {
|
||||
template += `
|
||||
<div class="view-mode">
|
||||
<button class="edit-position btn btn-inverse btn-small btn-block" data-marker-id="${marker.properties.recordIndex}">${localeService.t('mapMarkerEdit')}</button>
|
||||
</div>
|
||||
<div class="edit-mode">
|
||||
<p class="help" style="font-size: 12px;font-style: italic;">${localeService.t('mapMarkerMoveLabel')}</p>
|
||||
<p><span class="updated-position" style="font-size: 12px;"></span></p>
|
||||
<div>
|
||||
<button class="cancel-position btn btn-inverse btn-small btn-block" data-marker-id="${marker.properties.recordIndex}">${localeService.t('mapMarkerEditCancel')}</button>
|
||||
<button class="submit-position btn btn-inverse btn-small btn-block" data-marker-id="${marker.properties.recordIndex}">${localeService.t('mapMarkerEditSubmit')}</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
$content.append(template);
|
||||
|
||||
$content.find('.edit-mode').hide();
|
||||
//
|
||||
$content.on('click', '.edit-position', (event) => {
|
||||
let $el = $(event.currentTarget);
|
||||
let marker = getMarker($el.data('marker-id'));
|
||||
marker._originalPosition = marker.lngLat.wrap();
|
||||
$content.find('.view-mode').hide();
|
||||
$content.find('.edit-mode').show();
|
||||
$content.find('.help').show();
|
||||
isDraggable = true;
|
||||
|
||||
map.on('mousedown', mouseDown);
|
||||
});
|
||||
|
||||
$content.on('click', '.submit-position', (event) => {
|
||||
let $el = $(event.currentTarget);
|
||||
let marker = getMarker($el.data('marker-id'));
|
||||
|
||||
isDraggable = false;
|
||||
$content.find('.view-mode').show();
|
||||
$content.find('.help').hide();
|
||||
$content.find('.updated-position').html('');
|
||||
$content.find('.edit-mode').hide();
|
||||
|
||||
var popup = document.getElementsByClassName('mapboxgl-popup');
|
||||
if (popup[0]) popup[0].parentElement.removeChild(popup[0]);
|
||||
|
||||
marker.lngLat = {
|
||||
lng: cachedGeoJson.features[0].geometry.coordinates[0],
|
||||
lat: cachedGeoJson.features[0].geometry.coordinates[1]
|
||||
};
|
||||
marker.feature = marker.features[0];
|
||||
eventEmitter.emit('markerChange', {marker, position: marker.lngLat});
|
||||
});
|
||||
|
||||
|
||||
$content.on('click', '.cancel-position', (event) => {
|
||||
let $el = $(event.currentTarget);
|
||||
let marker = getMarker($el.data('marker-id'));
|
||||
isDraggable = false;
|
||||
$content.find('.view-mode').show();
|
||||
$content.find('.updated-position').html('');
|
||||
$content.find('.edit-mode').hide();
|
||||
$content.find('.help').hide();
|
||||
|
||||
var popup = document.getElementsByClassName('mapboxgl-popup');
|
||||
if (popup[0]) popup[0].parentElement.removeChild(popup[0]);
|
||||
|
||||
cachedGeoJson.features[0].geometry.coordinates = [marker._originalPosition.lng, marker._originalPosition.lat];
|
||||
map.getSource('data').setData(cachedGeoJson);
|
||||
});
|
||||
|
||||
// When the cursor enters a feature in the point layer, prepare for dragging.
|
||||
map.on('mouseenter', 'points', function () {
|
||||
if (!isDraggable) {
|
||||
return;
|
||||
}
|
||||
map.getCanvas().style.cursor = 'move';
|
||||
isCursorOverPoint = true;
|
||||
map.dragPan.disable();
|
||||
});
|
||||
|
||||
map.on('mouseleave', 'points', function () {
|
||||
if (!isDraggable) {
|
||||
return;
|
||||
}
|
||||
map.getCanvas().style.cursor = '';
|
||||
isCursorOverPoint = false;
|
||||
map.dragPan.enable();
|
||||
});
|
||||
|
||||
map.on('click', 'points', function (e) {
|
||||
markerCollection[e.features[0].properties.recordIndex] = e;
|
||||
var coordinates = e.features[0].geometry.coordinates.slice();
|
||||
|
||||
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
|
||||
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
|
||||
}
|
||||
|
||||
var popup = document.getElementsByClassName('mapboxgl-popup');
|
||||
// Check if there is already a popup on the map and if so, remove it
|
||||
if (popup[0]) popup[0].parentElement.removeChild(popup[0]);
|
||||
|
||||
popupDialog = new mapboxgl.Popup({closeOnClick: false}).setLngLat(coordinates)
|
||||
.setDOMContent($content.get(0))
|
||||
.addTo(map);
|
||||
|
||||
popupDialog.on('close', function (event) {
|
||||
if (editable) {
|
||||
resetMarkerPosition($content);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function mouseDown() {
|
||||
if (!isCursorOverPoint) return;
|
||||
|
||||
isDragging = true;
|
||||
|
||||
// Set a cursor indicator
|
||||
map.getCanvas().style.cursor = 'grab';
|
||||
|
||||
// Mouse events
|
||||
map.on('mousemove', onMove);
|
||||
map.once('mouseup', onUp);
|
||||
|
||||
var popup = document.getElementsByClassName('mapboxgl-popup');
|
||||
if (popup[0]) popup[0].parentElement.removeChild(popup[0]);
|
||||
}
|
||||
|
||||
function onMove(e) {
|
||||
if (!isDragging) return;
|
||||
var coords = e.lngLat;
|
||||
|
||||
// Set a UI indicator for dragging.
|
||||
map.getCanvas().style.cursor = 'grabbing';
|
||||
|
||||
// Update the Point feature in `geojson` coordinates
|
||||
// and call setData to the source layer `point` on it.
|
||||
cachedGeoJson.features[0].geometry.coordinates = [coords.lng, coords.lat];
|
||||
map.getSource('data').setData(cachedGeoJson);
|
||||
}
|
||||
|
||||
function onUp(e) {
|
||||
if (!isDragging) return;
|
||||
let position = e.lngLat;
|
||||
|
||||
map.getCanvas().style.cursor = '';
|
||||
isDragging = false;
|
||||
|
||||
// Unbind mouse events
|
||||
map.off('mousemove', onMove);
|
||||
$content.find('.updated-position').html(`${position.lat}<br>${position.lng}`);
|
||||
popupDialog = new mapboxgl.Popup({closeOnClick: false}).setLngLat(position)
|
||||
.setDOMContent($content.get(0))
|
||||
.addTo(map);
|
||||
|
||||
popupDialog.on('close', function (event) {
|
||||
if (editable) {
|
||||
resetMarkerPosition($content);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const resetMarkerPosition = ($content) => {
|
||||
let marker = getMarker($content.find('.edit-position').data('marker-id'))
|
||||
$content.find('.view-mode').show();
|
||||
$content.find('.updated-position').html('');
|
||||
$content.find('.edit-mode').hide();
|
||||
$content.find('.help').hide();
|
||||
isDraggable = false;
|
||||
if (marker._originalPosition !== undefined) {
|
||||
cachedGeoJson.features[0].geometry.coordinates = [marker._originalPosition.lng, marker._originalPosition.lat];
|
||||
map.getSource('data').setData(cachedGeoJson);
|
||||
}
|
||||
}
|
||||
|
||||
const getMarker = (markerId) => {
|
||||
return markerCollection[markerId];
|
||||
}
|
||||
|
||||
return {
|
||||
initialize, setCollection
|
||||
}
|
||||
}
|
||||
|
||||
export default markerGLCollection;
|
471
Phraseanet-production-client/src/components/lightbox/download.js
Normal file
471
Phraseanet-production-client/src/components/lightbox/download.js
Normal file
@@ -0,0 +1,471 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
const humane = require('humane-js');
|
||||
|
||||
const download = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let $container = null;
|
||||
|
||||
const initialize = (options) => {
|
||||
$container = options.$container;
|
||||
$container.on('click', '.basket_downloader', (event) => {
|
||||
event.preventDefault();
|
||||
_downloadBasket();
|
||||
})
|
||||
};
|
||||
const openModal = (datas) => {
|
||||
$('body').addClass('dialog-open');
|
||||
var $dialog = dialog.create(services, {
|
||||
size: 'Medium',
|
||||
title: localeService.t('export'),
|
||||
});
|
||||
|
||||
$('#DIALOG1').on('dialogclose', function(event) {
|
||||
$('body').removeClass('dialog-open');
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
data: 'lst=' + datas,
|
||||
url: `${url}prod/export/multi-export/`,
|
||||
success: function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onDownloadReady($dialog, window.exportConfig);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const _onDownloadReady = ($dialog, dataConfig) => {
|
||||
$('.tabs', $dialog.getDomElement()).tabs();
|
||||
|
||||
$('.close_button', $dialog.getDomElement()).bind('click', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
var tabs = $('.tabs', $dialog.getDomElement());
|
||||
|
||||
if (dataConfig.haveFtp === true) {
|
||||
$('#ftp_form_selector')
|
||||
.bind('change', function () {
|
||||
$('#ftp .ftp_form').hide();
|
||||
$('#ftp .ftp_form_' + $(this).val()).show();
|
||||
$('.ftp_folder_check', dialog.get(1).getDomElement())
|
||||
.unbind('change')
|
||||
.bind('change', function () {
|
||||
if ($(this).prop('checked')) {
|
||||
$(this).next().prop('disabled', false);
|
||||
} else {
|
||||
$(this).next().prop('disabled', true);
|
||||
}
|
||||
});
|
||||
})
|
||||
.trigger('change');
|
||||
}
|
||||
|
||||
$('a.TOUview').bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
var options = {
|
||||
size: 'Medium',
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.termOfUseTitle
|
||||
};
|
||||
|
||||
let termOfuseDialog = dialog.create(services, options, 2);
|
||||
|
||||
$.get($el.attr('href'), function (content) {
|
||||
termOfuseDialog.setContent(content);
|
||||
});
|
||||
});
|
||||
|
||||
$('.close_button').bind('click', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
$('#download .download_button').bind('click', function () {
|
||||
if (!check_subdefs($('#download'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_TOU($('#download'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var total = 0;
|
||||
var count = 0;
|
||||
|
||||
$('input[name="obj[]"]', $('#download')).each(function () {
|
||||
var total_el = $(
|
||||
'#download input[name=download_' + $(this).val() + ']'
|
||||
);
|
||||
var count_el = $(
|
||||
'#download input[name=count_' + $(this).val() + ']'
|
||||
);
|
||||
if ($(this).prop('checked')) {
|
||||
total += parseInt($(total_el).val(), 10);
|
||||
count += parseInt($(count_el).val(), 10);
|
||||
}
|
||||
});
|
||||
|
||||
if (count > 1 && total / 1024 / 1024 > dataConfig.maxDownload) {
|
||||
if (
|
||||
confirm(
|
||||
`${dataConfig.msg.fileTooLarge} \n ${dataConfig.msg
|
||||
.fileTooLargeAlt}`
|
||||
)
|
||||
) {
|
||||
$(
|
||||
'input[name="obj[]"]:checked',
|
||||
$('#download')
|
||||
).each(function (i, n) {
|
||||
$(
|
||||
'input[name="obj[]"][value="' + $(n).val() + '"]',
|
||||
$('#sendmail')
|
||||
).prop('checked', true);
|
||||
});
|
||||
$(document).find('input[name="taglistdestmail"]').tagsinput('add', dataConfig.user.email);
|
||||
|
||||
var tabs = $('.tabs', $dialog.getDomElement());
|
||||
tabs.tabs('option', 'active', 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
$('#download form').submit();
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
$('#order .order_button').bind('click', function () {
|
||||
let title = '';
|
||||
if (!check_TOU($('#order'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#order .order_button_loader').css('visibility', 'visible');
|
||||
|
||||
var options = $('#order form').serialize();
|
||||
|
||||
var $this = $(this);
|
||||
$this.prop('disabled', true).addClass('disabled');
|
||||
$.post(
|
||||
`${url}prod/order/`,
|
||||
options,
|
||||
function (data) {
|
||||
$this.prop('disabled', false).removeClass('disabled');
|
||||
|
||||
$('#order .order_button_loader').css(
|
||||
'visibility',
|
||||
'hidden'
|
||||
);
|
||||
|
||||
if (!data.error) {
|
||||
title = dataConfig.msg.success;
|
||||
} else {
|
||||
title = dataConfig.msg.warning;
|
||||
}
|
||||
|
||||
var options = {
|
||||
size: 'Alert',
|
||||
closeButton: true,
|
||||
title: title
|
||||
};
|
||||
|
||||
dialog.create(services, options, 2).setContent(data.msg);
|
||||
|
||||
if (!data.error) {
|
||||
showHumane(data.msg);
|
||||
|
||||
$dialog.close();
|
||||
} else {
|
||||
alert(data.msg);
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
'json'
|
||||
);
|
||||
});
|
||||
|
||||
$('#ftp .ftp_button').bind('click', function () {
|
||||
if (!check_subdefs($('#ftp'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_TOU($('#ftp'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#ftp .ftp_button_loader').show();
|
||||
|
||||
$('#ftp .ftp_form:hidden').remove();
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
var options_addr = $('#ftp_form_stock form:visible').serialize();
|
||||
var options_join = $('#ftp_joined').serialize();
|
||||
|
||||
$this.prop('disabled', true);
|
||||
$.post(
|
||||
`${url}prod/export/ftp/`,
|
||||
options_addr + '&' + options_join,
|
||||
function (data) {
|
||||
$this.prop('disabled', false);
|
||||
$('#ftp .ftp_button_loader').hide();
|
||||
|
||||
if (data.success) {
|
||||
showHumane(data.message);
|
||||
$dialog.close();
|
||||
} else {
|
||||
var alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(data.message);
|
||||
}
|
||||
return;
|
||||
},
|
||||
'json'
|
||||
);
|
||||
});
|
||||
|
||||
$('#ftp .tryftp_button').bind('click', function () {
|
||||
$('#ftp .tryftp_button_loader').css('visibility', 'visible');
|
||||
var $this = $(this);
|
||||
$this.prop('disabled', true);
|
||||
var options_addr = $('#ftp_form_stock form:visible').serialize();
|
||||
|
||||
$.post(
|
||||
`${url}prod/export/ftp/test/`,
|
||||
// no need to include 'ftp_joined' checkboxes to test ftp
|
||||
options_addr,
|
||||
function (data) {
|
||||
$('#ftp .tryftp_button_loader').css('visibility', 'hidden');
|
||||
|
||||
var options = {
|
||||
size: 'Alert',
|
||||
closeButton: true,
|
||||
title: data.success
|
||||
? dataConfig.msg.success
|
||||
: dataConfig.msg.warning
|
||||
};
|
||||
|
||||
dialog
|
||||
.create(services, options, 3)
|
||||
.setContent(data.message);
|
||||
|
||||
$this.prop('disabled', false);
|
||||
|
||||
return;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
function showHumane(data) {
|
||||
$('body').append('<div class="humane humane-libnotify-info">Email sending request submitted </div>');
|
||||
$('body').find('.humane-libnotify-info').html(data);
|
||||
setTimeout(hideHumane, 3000);
|
||||
}
|
||||
function hideHumane() {
|
||||
$('body').find('.humane').remove();
|
||||
}
|
||||
$('#sendmail .sendmail_button').bind('click', function () {
|
||||
if(!validEmail($('input[name="taglistdestmail"]', $('#sendmail')).val(), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_subdefs($('#sendmail'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_TOU($('#sendmail'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($('iframe[name=""]').length === 0) {
|
||||
$('body').append(
|
||||
'<iframe style="display:none;" name="sendmail_target"></iframe>'
|
||||
);
|
||||
}
|
||||
|
||||
$('#sendmail form').submit();
|
||||
showHumane($('#export-send-mail-notif').val());
|
||||
$dialog.close();
|
||||
|
||||
});
|
||||
|
||||
$('.datepicker', $dialog.getDomElement()).datepicker({
|
||||
changeYear: true,
|
||||
changeMonth: true,
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
|
||||
$(
|
||||
'a.undisposable_link',
|
||||
$dialog.getDomElement()
|
||||
).bind('click', function () {
|
||||
$(this).parent().parent().find('.undisposable').slideToggle();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(
|
||||
'input[name="obj[]"]',
|
||||
$('#download, #sendmail, #ftp')
|
||||
).bind('change', function () {
|
||||
var $form = $(this).closest('form');
|
||||
|
||||
if ($('input.caption[name="obj[]"]:checked', $form).length > 0) {
|
||||
$('div.businessfields', $form).show();
|
||||
} else {
|
||||
$('div.businessfields', $form).hide();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function validateEmail(email) {
|
||||
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(email);
|
||||
}
|
||||
|
||||
function validEmail(emailList, dataConfig) {
|
||||
//split emailList by ; , or whitespace and filter empty element
|
||||
let emails = emailList.split(/[ ,;]+/).filter(Boolean);
|
||||
let alert;
|
||||
for(let i=0; i < emails.length; i++) {
|
||||
if (!validateEmail(emails[i])) {
|
||||
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.invalidEmail);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function check_TOU(container, dataConfig) {
|
||||
let checkbox = $('input[name="TOU_accept"]', $(container));
|
||||
let go = checkbox.length === 0 || checkbox.prop('checked');
|
||||
let alert;
|
||||
if (!go) {
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Small',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.termOfUseAgree);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function check_subdefs(container, dataConfig) {
|
||||
let go = false;
|
||||
let required = false;
|
||||
let alert;
|
||||
|
||||
$('input[name="obj[]"]', $(container)).each(function () {
|
||||
if ($(this).prop('checked')) {
|
||||
go = true;
|
||||
}
|
||||
});
|
||||
|
||||
$('input.required, textarea.required', container).each(function (i, n) {
|
||||
if ($.trim($(n).val()) === '') {
|
||||
required = true;
|
||||
$(n).addClass('error');
|
||||
} else {
|
||||
$(n).removeClass('error');
|
||||
}
|
||||
});
|
||||
|
||||
if (required) {
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.requiredFields);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!go) {
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.missingSubdef);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function _downloadBasket() {
|
||||
var ids = $.map($('#sc_container .download_form').toArray(), function (el, i) {
|
||||
return $('input[name="basrec"]', $(el)).val();
|
||||
});
|
||||
openModal(ids.join(';'));
|
||||
}
|
||||
|
||||
/*function download(value) {
|
||||
var $dialog = dialog.create({title: localeService.t('export')});
|
||||
|
||||
$.post('/prod/export/multi-export/', 'lst=' + value, function (data) {
|
||||
|
||||
$dialog.setContent(data);
|
||||
|
||||
$('.tabs', $dialog.getDomElement()).tabs();
|
||||
|
||||
$('.close_button', $dialog.getDomElement()).bind('click', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
}*/
|
||||
|
||||
return {initialize, openModal}
|
||||
}
|
||||
|
||||
export default download;
|
1160
Phraseanet-production-client/src/components/lightbox/index.js
Normal file
1160
Phraseanet-production-client/src/components/lightbox/index.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,77 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
const listEditor = (services, options) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const { $container, listManagerInstance } = options;
|
||||
const $editor = $('#list-editor-search-results');
|
||||
const $form = $('#ListManager .editor').find('form[name="list-editor-search"]');
|
||||
|
||||
$('a.next, a.prev', $editor).bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
const page = $(this).attr('value');
|
||||
|
||||
$('input[name="page"]', $form).val(page);
|
||||
$form.trigger('submit');
|
||||
});
|
||||
|
||||
$('input[name="page"]', $form).val('');
|
||||
|
||||
$('th.sortable', $editor).bind('click', function () {
|
||||
|
||||
let $this = $(this);
|
||||
|
||||
let sort = $('input', $this).val();
|
||||
let ord = 'asc';
|
||||
|
||||
if ((sort === $('input[name="srt"]', $form).val()) && ($('input[name="ord"]', $form).val() === 'asc')) {
|
||||
ord = 'desc';
|
||||
}
|
||||
|
||||
$('input[name="srt"]', $form).val(sort);
|
||||
$('input[name="ord"]', $form).val(ord);
|
||||
|
||||
$form.trigger('submit');
|
||||
})
|
||||
.bind('mouseover', function () {
|
||||
$(this).addClass('hover');
|
||||
})
|
||||
.bind('mouseout', function () {
|
||||
$(this).removeClass('hover');
|
||||
});
|
||||
|
||||
$('tbody tr', $editor).bind('click', function () {
|
||||
|
||||
let $this = $(this);
|
||||
let usr_id = $('input[name="usr_id"]', $this).val();
|
||||
|
||||
let counters = $('#ListManager .counter.current, #ListManager .lists .list.selected .counter');
|
||||
|
||||
if ($this.hasClass('selected')) {
|
||||
$this.removeClass('selected');
|
||||
listManagerInstance.getList().removeUser(usr_id);
|
||||
|
||||
counters.each(function (i, el) {
|
||||
let n = parseInt($(el).text().split(' ')[0], 10);
|
||||
if($(el).hasClass('current'))
|
||||
$(el).text(n - 1 + ' people');
|
||||
else
|
||||
$(el).text(n - 1);
|
||||
});
|
||||
} else {
|
||||
$this.addClass('selected');
|
||||
listManagerInstance.getList().addUser(usr_id);
|
||||
|
||||
counters.each(function (i, el) {
|
||||
let n = parseInt($(el).text(), 10);
|
||||
|
||||
if($(el).hasClass('current'))
|
||||
$(el).text(n + 1 + ' people');
|
||||
else
|
||||
$(el).text(n + 1);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
export default listEditor;
|
605
Phraseanet-production-client/src/components/list/listManager.js
Normal file
605
Phraseanet-production-client/src/components/list/listManager.js
Normal file
@@ -0,0 +1,605 @@
|
||||
import $ from 'jquery';
|
||||
import {Lists, List} from './model/index';
|
||||
import listEditor from './listEditor';
|
||||
import listShare from './listShare';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import Selectable from '../utils/selectable';
|
||||
import pushAddUser from '../record/recordPush/addUser';
|
||||
import * as _ from 'underscore';
|
||||
const humane = require('humane-js');
|
||||
|
||||
const ListManager = function (services, options) {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const { containerId } = options;
|
||||
const url = configService.get('baseUrl');
|
||||
let $container;
|
||||
const _this = this;
|
||||
|
||||
this.list = null;
|
||||
this.container = $container = $(containerId);
|
||||
this.userList = new Lists();
|
||||
|
||||
this.removeUserItemsArray = [];
|
||||
this.addUserItemsArray = [];
|
||||
this.removeUserMethod = '';
|
||||
this.addUserMethod = '';
|
||||
|
||||
pushAddUser(services).initialize({$container: this.container});
|
||||
|
||||
$container.on('click', '.back_link', function () {
|
||||
$('#PushBox').show();
|
||||
$('#ListManager').hide();
|
||||
return false;
|
||||
})
|
||||
.on('click', '.push-list-share-action', (event) => {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
const listId = $el.data('list-id');
|
||||
|
||||
listShare(services).openModal({
|
||||
listId, modalOptions: {
|
||||
size: '288x500',
|
||||
closeButton: true,
|
||||
title: $el.attr('title')
|
||||
}, modalLevel: 2
|
||||
});
|
||||
return false;
|
||||
})
|
||||
.on('click', 'a.user_adder', function () {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $this.attr('href'),
|
||||
dataType: 'html',
|
||||
beforeSend: function () {
|
||||
var options = {
|
||||
size: 'Medium',
|
||||
title: $this.html()
|
||||
};
|
||||
dialog.create(services, options, 2).getDomElement().addClass('loading');
|
||||
},
|
||||
success: function (data) {
|
||||
dialog.get(2).getDomElement().removeClass('loading').empty().append(data);
|
||||
return;
|
||||
},
|
||||
error: function () {
|
||||
dialog.get(2).close();
|
||||
return;
|
||||
},
|
||||
timeout: function () {
|
||||
dialog.get(2).close();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
})
|
||||
.on('mouseenter', '.list-trash-btn', function (event) {
|
||||
var $el = $(event.currentTarget);
|
||||
$el.find('.image-normal').hide();
|
||||
$el.find('.image-hover').show();
|
||||
})
|
||||
.on('mouseleave', '.list-trash-btn', function (event) {
|
||||
var $el = $(event.currentTarget);
|
||||
$el.find('.image-normal').show();
|
||||
$el.find('.image-hover').hide();
|
||||
})
|
||||
.on('click', '.list-trash-btn', function (event) {
|
||||
var $el = $(event.currentTarget);
|
||||
var list_id = $el.parent().data('list-id');
|
||||
appEvents.emit('push.removeList', {
|
||||
list_id: list_id,
|
||||
container: containerId
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
var initLeft = () => {
|
||||
$container.on('click', '.push-refresh-list-action', (event) => {
|
||||
event.preventDefault();
|
||||
//$('a.list_refresh', $container).bind('click', (event) => {
|
||||
// /prod/lists/all/
|
||||
|
||||
var selectedList = $('.lists_manager_list.selected').data('list-id');
|
||||
|
||||
var callback = function (datas, selected) {
|
||||
$('.all-lists', $container).removeClass('loading').append(datas);
|
||||
|
||||
if (typeof selected === 'number') {
|
||||
$('.all-lists').find('.lists_manager_list[data-list-id="' + selected + '"]').addClass('selected');
|
||||
}
|
||||
// initLeft();
|
||||
};
|
||||
|
||||
$('.all-lists', $container).empty().addClass('loading');
|
||||
|
||||
this.userList.get(callback, 'html', selectedList);
|
||||
|
||||
});
|
||||
|
||||
$container.on('click', '.push-add-list-action', (event) => {
|
||||
event.preventDefault();
|
||||
var makeDialog = (box) => {
|
||||
|
||||
var buttons = {};
|
||||
|
||||
buttons[localeService.t('valider')] = () => {
|
||||
|
||||
var callbackOK = function () {
|
||||
$('a.list_refresh', $container).trigger('click');
|
||||
dialog.get(2).close();
|
||||
};
|
||||
|
||||
var name = $('input[name="name"]', dialog.get(2).getDomElement()).val();
|
||||
|
||||
if ($.trim(name) === '') {
|
||||
alert($('#push-list-name-empty').val());
|
||||
return;
|
||||
}
|
||||
|
||||
this.userList.create(name, callbackOK);
|
||||
};
|
||||
// /prod/lists/list/
|
||||
var options = {
|
||||
cancelButton: true,
|
||||
buttons: buttons,
|
||||
title: $('#push-new-list-title').val(),
|
||||
size: '450x170'
|
||||
};
|
||||
|
||||
const $dialog = dialog.create(services, options, 2);
|
||||
$dialog.getDomElement().closest('.ui-dialog').addClass('dialog_container dialog_add_list')
|
||||
.find('.ui-dialog-buttonset button:first-child .ui-button-text').text($('#btn-add').val());
|
||||
$dialog.setContent(box);
|
||||
};
|
||||
|
||||
var html = _.template($('#list_editor_dialog_add_tpl').html());
|
||||
makeDialog(html);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
/*$('li.list a.list_link', $container).bind('click', function (event) {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$this.closest('.lists').find('.list.selected').removeClass('selected');
|
||||
$this.parent('li.list').addClass('selected');
|
||||
return false;
|
||||
});*/
|
||||
$container.on('click', '.list-edit-action', (event) => {
|
||||
event.preventDefault();
|
||||
_this.removeUserItemsArray = [];
|
||||
_this.addUserItemsArray = [];
|
||||
_this.removeUserMethod = '';
|
||||
_this.addUserMethod = '';
|
||||
|
||||
let $el = $(event.currentTarget);
|
||||
const listId = $el.data('list-id');
|
||||
const el_url = $el.attr('href');
|
||||
|
||||
const callbackList = function (list) {
|
||||
for (let i in list.entries) {
|
||||
this.selectUser(list.entries[i].User);
|
||||
}
|
||||
};
|
||||
|
||||
$el.closest('.lists').find('.list').removeClass('selected');
|
||||
$el.parent().addClass('selected');
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: `${url}prod/push/edit-list/${listId}/`,
|
||||
dataType: 'html',
|
||||
success: (data) => {
|
||||
this.workOn(listId);
|
||||
$('.editor', $container).removeClass('loading').append(data);
|
||||
this.loadList(el_url, callbackList);
|
||||
initRight();
|
||||
listEditor(services, {
|
||||
$container, listManagerInstance: _this
|
||||
});
|
||||
},
|
||||
beforeSend: function () {
|
||||
$('.editor', $container).empty().addClass('loading');
|
||||
}
|
||||
});
|
||||
});
|
||||
$container.on('click', '.listmanager-delete-list-user-action', (event) => {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
const listId = $el.data('list-id');
|
||||
const userId = $el.data('user-id');
|
||||
|
||||
|
||||
var badge = $(this).closest('.badge');
|
||||
// var usr_id = badge.find('input[name="id"]').val();
|
||||
this.getList().removeUser(userId, function (list, data) {
|
||||
badge.remove();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var initRight = function () {
|
||||
var $container = $('#ListManager .editor');
|
||||
var selection = new Selectable(services, $('.user_content .badges', _this.container), {
|
||||
selector: '.badge'
|
||||
});
|
||||
|
||||
$('form[name="list-editor-search"]', $container).bind('submit', function (event) {
|
||||
event.preventDefault();
|
||||
var $this = $(this);
|
||||
var dest = $('.list-editor-results', $container);
|
||||
|
||||
$.ajax({
|
||||
url: $this.attr('action'),
|
||||
type: $this.attr('method'),
|
||||
dataType: 'html',
|
||||
data: $this.serializeArray(),
|
||||
beforeSend: function () {
|
||||
dest.empty().addClass('loading');
|
||||
},
|
||||
success: function (datas) {
|
||||
dest.empty().removeClass('loading').append(datas);
|
||||
listEditor(services, {
|
||||
$container, listManagerInstance: _this
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('form[name="list-editor-search"] select, form[name="list-editor-search"] input[name="ListUser"]', $container).bind('change', function () {
|
||||
$(this).closest('form').trigger('submit');
|
||||
});
|
||||
|
||||
$('.EditToggle', $container).bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
$('.content.readselect, .content.readwrite, .editor_header', $('#ListManager')).toggle();
|
||||
});
|
||||
$('.Refresher', $container).bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
$('#ListManager ul.lists .list.selected a').trigger('click');
|
||||
});
|
||||
|
||||
$('form[name="SaveName"]', $container).bind('submit', function () {
|
||||
var $this = $(this);
|
||||
|
||||
$.ajax({
|
||||
type: $this.attr('method'),
|
||||
url: $this.attr('action'),
|
||||
dataType: 'json',
|
||||
data: $this.serializeArray(),
|
||||
beforeSend: function () {
|
||||
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
$('#ListManager .lists .list_refresh').trigger('click');
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
return;
|
||||
},
|
||||
error: function () {
|
||||
|
||||
return;
|
||||
},
|
||||
timeout: function () {
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// //button.deleter
|
||||
// $('.listmanager-delete-list-action', $container).bind('click', function (event) {
|
||||
|
||||
// var list_id = $(this).data('list-id');
|
||||
|
||||
// var makeDialog = function (box) {
|
||||
|
||||
// var buttons = {};
|
||||
|
||||
// buttons[localeService.t('valider')] = function () {
|
||||
|
||||
// var callbackOK = function () {
|
||||
// $('#ListManager .all-lists a.list_refresh').trigger('click');
|
||||
// dialog.get(2).close();
|
||||
// };
|
||||
|
||||
// var List = new List(list_id);
|
||||
// List.remove(callbackOK);
|
||||
// };
|
||||
|
||||
// var options = {
|
||||
// cancelButton: true,
|
||||
// buttons: buttons,
|
||||
// size: 'Alert'
|
||||
// };
|
||||
|
||||
// dialog.create(services, options, 2).setContent(box);
|
||||
// };
|
||||
|
||||
// var html = _.template($('#list_editor_dialog_delete_tpl').html());
|
||||
|
||||
// makeDialog(html);
|
||||
|
||||
// return false;
|
||||
// });
|
||||
|
||||
$('input[name="users-search"]', $container).autocomplete({
|
||||
minLength: 2,
|
||||
source: function (request, response) {
|
||||
$.ajax({
|
||||
url: `${url}prod/push/search-user/`,
|
||||
dataType: 'json',
|
||||
data: {
|
||||
query: request.term
|
||||
},
|
||||
success: function (data) {
|
||||
response(data);
|
||||
}
|
||||
});
|
||||
},
|
||||
focus: function (event, ui) {
|
||||
// $('input[name="users-search"]').val(ui.item.label);
|
||||
},
|
||||
select: function (event, ui) {
|
||||
if (ui.item.type === 'USER') {
|
||||
_this.selectUser(ui.item);
|
||||
_this.updateUsersHandler('add', ui.item.usr_id);
|
||||
} else if (ui.item.type === 'LIST') {
|
||||
for (let e in ui.item.entries) {
|
||||
_this.selectUser(ui.item.entries[e].User);
|
||||
_this.updateUsersHandler('add', ui.item.entries[e].User.usr_id);
|
||||
}
|
||||
}
|
||||
$('#saveListFooter').show();
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.data('ui-autocomplete')._renderItem = function (ul, item) {
|
||||
var html = '';
|
||||
|
||||
if (item.type === 'USER') {
|
||||
html = _.template($('#list_user_tpl').html())({
|
||||
|
||||
item: item
|
||||
});
|
||||
} else if (item.type === 'LIST') {
|
||||
html = _.template($('#list_list_tpl').html())({
|
||||
item: item
|
||||
});
|
||||
}
|
||||
|
||||
return $(html).data('ui-autocomplete-item', item).appendTo(ul);
|
||||
};
|
||||
|
||||
$('.user_content .badges', _this.container).disableSelection();
|
||||
|
||||
$container.on('click', '.content .options .select-all', function () {
|
||||
selection.selectAll();
|
||||
});
|
||||
|
||||
$container.on('click', '.content .options .unselect-all', function () {
|
||||
selection.empty();
|
||||
});
|
||||
|
||||
$container.on('click', '.content .options .delete-selection', function () {
|
||||
var $elems = $('#ListManager .badges.selectionnable .badge.selected');
|
||||
_.each($elems, function(item) {
|
||||
var $elem = $(item);
|
||||
var $elemID = $elem.find('input[name=id]').val();
|
||||
if($elem.hasClass('selected')
|
||||
&& _this.removeUserItemsArray.indexOf($elemID) === -1) {
|
||||
_this.updateUsersHandler('remove', $elemID);
|
||||
}
|
||||
});
|
||||
|
||||
$elems.fadeOut(300, 'swing', function() {
|
||||
$(this).remove();
|
||||
$('#saveListFooter').show();
|
||||
});
|
||||
});
|
||||
$container.on('submit', 'form.list_saver', function (event) {
|
||||
event.preventDefault();
|
||||
var $form = $(event.currentTarget);
|
||||
var name = $('.header h2', $container).text();
|
||||
var users = _this.getUsers();
|
||||
|
||||
if (users.length === 0) {
|
||||
humane.error('No users');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (_this.removeUserMethod === 'remove' && _this.removeUserItemsArray.length > 0) {
|
||||
var $editor = $('#list-editor-search-results');
|
||||
|
||||
_.each(_this.removeUserItemsArray, function (item) {
|
||||
|
||||
$('tbody tr', $editor).each(function(i, el) {
|
||||
var $el = $(el);
|
||||
var $elID = $('input[name="usr_id"]', $el).val();
|
||||
if(item == $elID)
|
||||
$el.removeClass('selected');
|
||||
});
|
||||
|
||||
_this.getList().removeUser(item);
|
||||
});
|
||||
|
||||
var ListCounter = $('#ListManager .counter.current, #ListManager .lists .list.selected .counter');
|
||||
|
||||
ListCounter.each(function (i, el) {
|
||||
var n = parseInt($(el).text(), 10);
|
||||
if($(el).hasClass('current'))
|
||||
$(el).text(n - _this.removeUserItemsArray.length + ' people');
|
||||
else
|
||||
$(el).text(n - _this.removeUserItemsArray.length);
|
||||
});
|
||||
|
||||
$('#saveListFooter').hide();
|
||||
_this.removeUserItemsArray = [];
|
||||
_this.removeUserMethod = '';
|
||||
}
|
||||
else if (_this.addUserMethod === 'add' && _this.addUserItemsArray.length > 0) {
|
||||
var $editor = $('#list-editor-search-results');
|
||||
|
||||
_.each(_this.addUserItemsArray, function (item) {
|
||||
|
||||
$('tbody tr', $editor).each(function(i, el) {
|
||||
|
||||
var $el = $(el);
|
||||
var $elID = $('input[name="usr_id"]', $el).val();
|
||||
|
||||
if(item == $elID)
|
||||
$el.addClass('selected');
|
||||
});
|
||||
|
||||
_this.getList().addUser(item);
|
||||
});
|
||||
|
||||
var ListCounter = $('#ListManager .counter.current, #ListManager .lists .list.selected .counter');
|
||||
|
||||
ListCounter.each(function (i, el) {
|
||||
var n = parseInt($(el).text(), 10);
|
||||
|
||||
if($(el).hasClass('current'))
|
||||
$(el).text(n + _this.addUserItemsArray.length + ' people');
|
||||
else
|
||||
$(el).text(n + _this.addUserItemsArray.length);
|
||||
});
|
||||
|
||||
$('#saveListFooter').hide();
|
||||
_this.addUserItemsArray = [];
|
||||
_this.addUserMethod = '';
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$container.on('click', '.badges a.deleter', function (event) {
|
||||
var badge = $(event.currentTarget).closest('.badge');
|
||||
var usr_id = badge.find('input[name="id"]').val();
|
||||
var ListCounter = $('#ListManager .counter.current, #ListManager .lists .list.selected .counter');
|
||||
var $editor = $('#list-editor-search-results');
|
||||
|
||||
var callback = function callback(list, datas) {
|
||||
ListCounter.each(function (i, el) {
|
||||
var n = parseInt($(el).text(), 10);
|
||||
|
||||
if($(el).hasClass('current'))
|
||||
$(el).text(n - 1 + ' people');
|
||||
else
|
||||
$(el).text(n - 1);
|
||||
});
|
||||
badge.fadeOut('300', 'swing', function() {
|
||||
badge.remove();
|
||||
});
|
||||
};
|
||||
|
||||
_this.getList().removeUser(usr_id, callback);
|
||||
|
||||
$('tbody tr', $editor).each(function(i, el) {
|
||||
var $el = $(el);
|
||||
var $elID = $('input[name="usr_id"]', $el).val();
|
||||
|
||||
if(usr_id === $elID)
|
||||
$el.removeClass('selected');
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
initLeft();
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
ListManager.prototype = {
|
||||
selectUser: function (user) {
|
||||
if (typeof user !== 'object') {
|
||||
if (window.console) {
|
||||
console.log('trying to select a user with wrong datas');
|
||||
}
|
||||
}
|
||||
if ($('.badge_' + user.usr_id, this.container).length > 0) {
|
||||
humane.info('User already selected');
|
||||
return;
|
||||
}
|
||||
else {
|
||||
var html = _.template($('#list_manager_badge_tpl').html())({
|
||||
user: user
|
||||
});
|
||||
|
||||
// p4.Feedback.appendBadge(html);
|
||||
// this.getList().addUser(user.usr_id);
|
||||
this.appendBadge(html);
|
||||
}
|
||||
},
|
||||
workOn: function (list_id) {
|
||||
this.list = new List(list_id);
|
||||
},
|
||||
getList: function () {
|
||||
return this.list;
|
||||
},
|
||||
appendBadge: function (datas) {
|
||||
$('#ListManager .badges').append(datas);
|
||||
},
|
||||
createList: function (options) {
|
||||
let { name, collection } = options;
|
||||
|
||||
this.userList.create(name, function (list) {
|
||||
list.addUsers(collection);
|
||||
});
|
||||
},
|
||||
removeList: function (list_id, callback) {
|
||||
this.list = new List(list_id);
|
||||
this.list.remove(callback);
|
||||
},
|
||||
loadList: function (url, callback) {
|
||||
var $this = this;
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (typeof callback === 'function') {
|
||||
callback.call($this, data);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
updateUsers: function (action) {
|
||||
if(action === 'remove') {
|
||||
|
||||
}
|
||||
return removedItems;
|
||||
},
|
||||
getUsers: function () {
|
||||
return $('.user_content .badge', this.container).map(function () {
|
||||
return $('input[name="id"]', $(this)).val();
|
||||
});
|
||||
},
|
||||
updateUsersHandler: function (method, item) {
|
||||
if (method === 'remove') {
|
||||
this.removeUserItemsArray.push(item);
|
||||
this.removeUserMethod = method;
|
||||
}
|
||||
else if (method === 'add') {
|
||||
this.addUserItemsArray.push(item);
|
||||
this.addUserMethod = method;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export default ListManager;
|
149
Phraseanet-production-client/src/components/list/listShare.js
Normal file
149
Phraseanet-production-client/src/components/list/listShare.js
Normal file
@@ -0,0 +1,149 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import * as _ from 'underscore';
|
||||
const humane = require('humane-js');
|
||||
|
||||
const listShare = (services, options) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let $dialog = null;
|
||||
|
||||
|
||||
const initialize = () => {
|
||||
};
|
||||
|
||||
|
||||
const openModal = (options) => {
|
||||
let { listId, modalOptions, modalLevel } = options;
|
||||
|
||||
$dialog = dialog.create(services, modalOptions, modalLevel);
|
||||
$dialog.getDomElement().closest('.ui-dialog').addClass('dialog_container dialog_share_list');
|
||||
|
||||
return $.get(`${url}prod/lists/list/${listId}/share/`, function (data) {
|
||||
$dialog.setContent(data);
|
||||
onModalReady(listId);
|
||||
});
|
||||
};
|
||||
|
||||
const onModalReady = (listId) => {
|
||||
let $container = $('#ListShare');
|
||||
let $completer_form = $('form[name="list_share_user"]', $container);
|
||||
let $owners_form = $('form[name="owners"]', $container);
|
||||
let $autocompleter = $('input[name="user"]', $completer_form);
|
||||
let $dialog = dialog.get(2);
|
||||
|
||||
$completer_form.bind('submit', function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
$('select[name="role"]', $owners_form).bind('change', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
const userId = $el.data('user-id');
|
||||
|
||||
shareWith(userId, $el.val());
|
||||
|
||||
return false;
|
||||
});
|
||||
$container.on('click', '.listmanager-share-delete-user-action', (event) => {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
const userId = $el.data('user-id');
|
||||
|
||||
let $owner = $el.closest('.owner');
|
||||
|
||||
unShareWith(userId, function (data) {
|
||||
$owner.remove();
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
function shareWith(userId, role) {
|
||||
role = typeof role === 'undefined' ? 1 : role;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/lists/list/${listId}/share/${userId}/`,
|
||||
dataType: 'json',
|
||||
data: {role: role},
|
||||
beforeSend: function () {
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
|
||||
$('.push-list-share-action').trigger('click');
|
||||
$dialog.refresh();
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function unShareWith(userId, callback) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/lists/list/${listId}/unshare/${userId}/`,
|
||||
dataType: 'json',
|
||||
data: {},
|
||||
beforeSend: function () {
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
callback(data);
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
$dialog.refresh();
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$autocompleter.autocomplete({
|
||||
minLength: 2,
|
||||
source: function (request, response) {
|
||||
$.ajax({
|
||||
url: `${url}prod/push/search-user/`,
|
||||
dataType: 'json',
|
||||
data: {
|
||||
query: request.term
|
||||
},
|
||||
success: function (data) {
|
||||
response(data);
|
||||
}
|
||||
});
|
||||
},
|
||||
select: function (event, ui) {
|
||||
if (ui.item.type === 'USER') {
|
||||
shareWith(ui.item.usr_id);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.data('ui-autocomplete')._renderItem = function (ul, item) {
|
||||
if (item.type === 'USER') {
|
||||
var html = _.template($('#list_user_tpl').html())({
|
||||
item: item
|
||||
});
|
||||
|
||||
return $(html).data('ui-autocomplete-item', item).appendTo(ul);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
openModal
|
||||
};
|
||||
};
|
||||
|
||||
export default listShare;
|
199
Phraseanet-production-client/src/components/list/model/index.js
Normal file
199
Phraseanet-production-client/src/components/list/model/index.js
Normal file
@@ -0,0 +1,199 @@
|
||||
import $ from 'jquery';
|
||||
const humane = require('humane-js');
|
||||
|
||||
var Lists = function () {
|
||||
|
||||
};
|
||||
|
||||
var List = function (id) {
|
||||
|
||||
if (parseInt(id, 10) <= 0) {
|
||||
throw 'Invalid list id';
|
||||
}
|
||||
|
||||
this.id = id;
|
||||
};
|
||||
|
||||
Lists.prototype = {
|
||||
create: function (name, callback) {
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
// @TODO - load baseUrl from configService
|
||||
url: '/prod/lists/list/',
|
||||
dataType: 'json',
|
||||
data: {name: name},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
var list = new List(data.list_id);
|
||||
callback(list);
|
||||
}
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
get: function (callback, type, selectedList) {
|
||||
|
||||
type = typeof type === 'undefined' ? 'json' : type;
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
// @TODO - load baseUrl from configService
|
||||
url: '/prod/lists/all/',
|
||||
dataType: type,
|
||||
data: {},
|
||||
success: function (data) {
|
||||
if (type === 'json') {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(data.result);
|
||||
}
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
} else {
|
||||
if (typeof callback === 'function') {
|
||||
callback(data, selectedList);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
List.prototype = {
|
||||
addUsers: function (arrayUsers, callback) {
|
||||
|
||||
if (!arrayUsers instanceof Array) {
|
||||
throw 'addUsers takes array as argument';
|
||||
}
|
||||
|
||||
var $this = this;
|
||||
var data = {usr_ids: $(arrayUsers).toArray()};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
// @TODO - load baseUrl from configService
|
||||
url: '/prod/lists/list/' + $this.id + '/add/',
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback($this, data);
|
||||
}
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
addUser: function (usr_id, callback) {
|
||||
this.addUsers([usr_id], callback);
|
||||
},
|
||||
remove: function (callback) {
|
||||
|
||||
var $this = this;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
// @TODO - load baseUrl from configService
|
||||
url: '/prod/lists/list/' + this.id + '/delete/',
|
||||
dataType: 'json',
|
||||
data: {},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback($this);
|
||||
}
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
update: function (name, callback) {
|
||||
|
||||
var $this = this;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
// @TODO - load baseUrl from configService
|
||||
url: '/prod/lists/list/' + this.id + '/update/',
|
||||
dataType: 'json',
|
||||
data: {name: name},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback($this);
|
||||
}
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
removeUser: function (usr_id, callback) {
|
||||
|
||||
var $this = this;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
// @TODO - load baseUrl from configService
|
||||
url: '/prod/lists/list/' + this.id + '/remove/' + usr_id + '/',
|
||||
dataType: 'json',
|
||||
data: {},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback($this, data);
|
||||
}
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
get: function (callback) {
|
||||
|
||||
var $this = this;
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
// @TODO - load baseUrl from configService
|
||||
url: '/prod/lists/list/' + this.id + '/',
|
||||
dataType: 'json',
|
||||
data: {},
|
||||
success: function (data) {
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback($this, data);
|
||||
}
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export {Lists, List};
|
73
Phraseanet-production-client/src/components/locale/index.js
Normal file
73
Phraseanet-production-client/src/components/locale/index.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import i18next from 'i18next';
|
||||
import Backend from 'i18next-xhr-backend';
|
||||
import $ from 'jquery';
|
||||
import * as Rx from 'rx';
|
||||
|
||||
let instance = null;
|
||||
class LocaleService {
|
||||
constructor(options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
// can be instanciated only once
|
||||
if (!instance) {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
if (options.locale === undefined) {
|
||||
options.locale = 'fr';
|
||||
}
|
||||
this.locale = options.locale;
|
||||
this.isCached = false;
|
||||
this.cachedTranslations = {};
|
||||
this.configService = options.configService;
|
||||
this.path = this.configService.get('translations');
|
||||
return instance;
|
||||
}
|
||||
|
||||
t(key) {
|
||||
if (this.isCached && this.translate !== undefined) {
|
||||
return this.translate(key);
|
||||
} else {
|
||||
throw new Error('locale not loaded');
|
||||
}
|
||||
}
|
||||
|
||||
getLocale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
getTranslations() {
|
||||
return this.cachedTranslations;
|
||||
}
|
||||
|
||||
fetchTranslations(data) {
|
||||
data = data || {};
|
||||
let i18nPromise = $.Deferred();
|
||||
i18next
|
||||
.use(Backend)
|
||||
.init({
|
||||
lng: this.locale,
|
||||
backend: {
|
||||
loadPath: this.path,
|
||||
|
||||
}
|
||||
}, (err, t) => {
|
||||
this.isCached = true;
|
||||
this.translate = t;
|
||||
this.cachedTranslations = i18next.getResourceBundle(this.locale);
|
||||
i18nPromise.resolve(instance);
|
||||
if (data.callback !== undefined) {
|
||||
data.callback();
|
||||
}
|
||||
//resolve(this.i18n);
|
||||
});
|
||||
// });
|
||||
this.i18n = i18nPromise.promise();
|
||||
this.stream = Rx.Observable.fromPromise(this.i18n);
|
||||
return this.i18n;
|
||||
}
|
||||
}
|
||||
|
||||
export default LocaleService;
|
@@ -0,0 +1,49 @@
|
||||
import $ from 'jquery';
|
||||
require('./../../phraseanet-common/components/vendors/contextMenu');
|
||||
|
||||
const mainMenu = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const $container = $('body');
|
||||
|
||||
const initialize = () => {
|
||||
_bindEvents();
|
||||
return true;
|
||||
};
|
||||
|
||||
const _bindEvents = () => {
|
||||
/**
|
||||
* mainMenu > Publication link
|
||||
*/
|
||||
$container.on('click', '.state-navigation', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
|
||||
// @TODO loop through each state args:
|
||||
|
||||
_stateNavigator($el.data('state'));
|
||||
});
|
||||
/**
|
||||
* mainMenu > help context menu
|
||||
*/
|
||||
|
||||
/* $('body').on('click', '#help-trigger', function (event) {
|
||||
$('#mainMenu .helpcontextmenu').toggleClass('shown');
|
||||
});*/
|
||||
};
|
||||
|
||||
const _stateNavigator = (...state) => {
|
||||
let [stateName, stateArgs] = state;
|
||||
|
||||
switch (stateName) {
|
||||
case 'publication':
|
||||
appEvents.emit(`${stateName}.activeState`); // fetch
|
||||
break;
|
||||
default:
|
||||
console.log('navigation state error: state "' + stateName + '" not found');
|
||||
}
|
||||
|
||||
};
|
||||
return { initialize };
|
||||
};
|
||||
|
||||
export default mainMenu;
|
98
Phraseanet-production-client/src/components/notify/index.js
Normal file
98
Phraseanet-production-client/src/components/notify/index.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import $ from 'jquery';
|
||||
// import user from '../user/index.js';
|
||||
import notifyLayout from './notifyLayout';
|
||||
import notifyService from './notifyService';
|
||||
import * as Rx from 'rx';
|
||||
import merge from 'lodash.merge';
|
||||
const notify = (services) => {
|
||||
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const defaultPollingTime = 10000;
|
||||
const defaultConfig = {
|
||||
url: null,
|
||||
moduleId: null,
|
||||
userId: null,
|
||||
_isValid: false
|
||||
};
|
||||
|
||||
const initialize = () => {
|
||||
notifyLayout(services).initialize();
|
||||
};
|
||||
|
||||
const createNotifier = (state) => {
|
||||
if (state === undefined) {
|
||||
return defaultConfig;
|
||||
}
|
||||
if (state.url === undefined) {
|
||||
return defaultConfig;
|
||||
}
|
||||
|
||||
return merge({}, defaultConfig, {
|
||||
url: state.url,
|
||||
moduleId: state.moduleId,
|
||||
userId: state.userId,
|
||||
_isValid: true
|
||||
});
|
||||
};
|
||||
|
||||
//const appendNotifications = (content) => notifyUiComponent().addNotifications(content);
|
||||
|
||||
const isValid = (notificationInstance) => notificationInstance._isValid || false;
|
||||
|
||||
const poll = (notificationInstance) => {
|
||||
|
||||
let notificationSource = Rx.Observable
|
||||
.fromPromise(notifyService({
|
||||
configService: configService
|
||||
}).getNotification({
|
||||
module: notificationInstance.moduleId,
|
||||
usr: notificationInstance.userId
|
||||
}));
|
||||
|
||||
notificationSource.subscribe(
|
||||
x => onPollSuccess(x, notificationInstance),
|
||||
e => onPollError(e, notificationInstance),
|
||||
() => {}
|
||||
);
|
||||
};
|
||||
const onPollSuccess = (data, notificationInstance) => {
|
||||
// broadcast session refresh event
|
||||
appEvents.emit('session.refresh', data);
|
||||
// broadcast notification refresh event
|
||||
if (data.changed.length > 0) {
|
||||
appEvents.emit('notification.refresh', data);
|
||||
}
|
||||
// append notification content
|
||||
notifyLayout(services).addNotifications(data.notifications);
|
||||
|
||||
let t = 120000;
|
||||
if (data.apps && parseInt(data.apps, 10) > 1) {
|
||||
t = Math.round((Math.sqrt(parseInt(data.apps, 10) - 1) * 1.3 * 60000));
|
||||
}
|
||||
|
||||
window.setTimeout(poll, t, notificationInstance);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const onPollError = (data, notificationInstance) => {
|
||||
if (data.status === 'disconnected' || data.status === 'session') {
|
||||
appEvents.emit('user.disconnected', data);
|
||||
return false;
|
||||
}
|
||||
window.setTimeout(poll, defaultPollingTime, notificationInstance);
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
initialize,
|
||||
/*appendNotifications: (content) => {
|
||||
notifyLayout().addNotifications(content)
|
||||
},*/
|
||||
createNotifier,
|
||||
isValid,
|
||||
poll
|
||||
};
|
||||
};
|
||||
|
||||
export default notify;
|
@@ -0,0 +1,245 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
// import user from '../user/index.js';
|
||||
|
||||
|
||||
const notifyLayout = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const $notificationBoxContainer = $('#notification_box');
|
||||
const $notificationTrigger = $('.notification_trigger');
|
||||
let $notificationDialog = $('#notifications-dialog');
|
||||
const initialize = () => {
|
||||
$notificationTrigger.on('mousedown', (event) => {
|
||||
event.stopPropagation();
|
||||
const $target = $(event.currentTarget);
|
||||
if ($target.hasClass('open')) {
|
||||
$notificationBoxContainer.hide();
|
||||
$target.removeClass('open');
|
||||
clear_notifications();
|
||||
} else {
|
||||
$notificationBoxContainer.show();
|
||||
|
||||
setBoxHeight();
|
||||
|
||||
$target.addClass('open');
|
||||
read_notifications();
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('mousedown', () => {
|
||||
if ($notificationTrigger.hasClass('open')) {
|
||||
$notificationTrigger.trigger('click');
|
||||
}
|
||||
|
||||
if ($notificationTrigger.hasClass('open')) {
|
||||
$notificationBoxContainer.hide();
|
||||
$notificationTrigger.removeClass('open');
|
||||
clear_notifications();
|
||||
}
|
||||
});
|
||||
|
||||
$notificationBoxContainer
|
||||
.on('mousedown', (event) => {
|
||||
event.stopPropagation();
|
||||
})
|
||||
.on('mouseover', '.notification', (event) => {
|
||||
$(event.currentTarget).addClass('hover');
|
||||
})
|
||||
.on('mouseout', '.notification', (event) => {
|
||||
$(event.currentTarget).removeClass('hover');
|
||||
})
|
||||
.on('click', '.notification__print-action', (event) => {
|
||||
event.preventDefault();
|
||||
const $el = $(event.currentTarget);
|
||||
const page = $el.data('page');
|
||||
print_notifications(page);
|
||||
});
|
||||
|
||||
$(window).bind('resize', function () {
|
||||
setBoxPosition();
|
||||
});
|
||||
setBoxPosition();
|
||||
|
||||
};
|
||||
|
||||
const addNotifications = (notificationContent) => {
|
||||
// var box = $('#notification_box');
|
||||
$notificationBoxContainer.empty().append(notificationContent);
|
||||
|
||||
if ($notificationBoxContainer.is(':visible')) {
|
||||
setBoxHeight();
|
||||
}
|
||||
|
||||
if ($('.notification.unread', $notificationBoxContainer).length > 0) {
|
||||
$('.counter', $notificationTrigger)
|
||||
.empty()
|
||||
.append($('.notification.unread', $notificationBoxContainer).length);
|
||||
$('.counter', $notificationTrigger).css('visibility', 'visible');
|
||||
|
||||
} else {
|
||||
$('.notification_trigger .counter').css('visibility', 'hidden').empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const setBoxHeight = () => {
|
||||
//var box = $('#notification_box');
|
||||
var not = $('.notification', $notificationBoxContainer);
|
||||
var n = not.length;
|
||||
var not_t = $('.notification_title', $notificationBoxContainer);
|
||||
var n_t = not_t.length;
|
||||
|
||||
var h = not.outerHeight() * n + not_t.outerHeight() * n_t;
|
||||
h = h > 350 ? 350 : h;
|
||||
|
||||
$notificationBoxContainer.stop().animate({height: h});
|
||||
};
|
||||
|
||||
const setBoxPosition = () => {
|
||||
if ($notificationTrigger.length > 0) {
|
||||
var leftOffset = Math.round($notificationTrigger.offset().left);
|
||||
if(leftOffset == 0) {
|
||||
$notificationBoxContainer.css({
|
||||
left: 20
|
||||
});
|
||||
}else {
|
||||
$notificationBoxContainer.css({
|
||||
left: Math.round($notificationTrigger.offset().left - 1)
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const print_notifications = (page) => {
|
||||
|
||||
page = parseInt(page, 10);
|
||||
var buttons = {};
|
||||
|
||||
buttons[localeService.t('fermer')] = function () {
|
||||
$notificationDialog.dialog('close');
|
||||
};
|
||||
|
||||
if ($notificationDialog.length === 0) {
|
||||
$('body').append('<div id="notifications-dialog" class="loading"></div>');
|
||||
$notificationDialog = $('#notifications-dialog');
|
||||
}
|
||||
|
||||
$notificationDialog
|
||||
.dialog({
|
||||
title: $('#notification-title').val(),
|
||||
autoOpen: false,
|
||||
closeOnEscape: true,
|
||||
resizable: false,
|
||||
draggable: false,
|
||||
modal: true,
|
||||
width: 500,
|
||||
height: 400,
|
||||
overlay: {
|
||||
backgroundColor: '#000',
|
||||
opacity: 0.7
|
||||
},
|
||||
close: function (event, ui) {
|
||||
$notificationDialog.dialog('destroy').remove();
|
||||
}
|
||||
}).dialog('option', 'buttons', buttons).dialog('open').on('click','.notification_next .notification__print-action', function (event) {
|
||||
event.preventDefault();
|
||||
var $el = $(event.currentTarget);
|
||||
var page = $el.data('page');
|
||||
print_notifications(page);
|
||||
});
|
||||
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '/user/notifications/',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
page: page
|
||||
},
|
||||
error: function (data) {
|
||||
$notificationDialog.removeClass('loading');
|
||||
},
|
||||
timeout: function (data) {
|
||||
$notificationDialog.removeClass('loading');
|
||||
},
|
||||
success: function (data) {
|
||||
$notificationDialog.removeClass('loading');
|
||||
|
||||
|
||||
if (page === 0) {
|
||||
$notificationDialog.empty();
|
||||
} else {
|
||||
$('.notification_next', $notificationDialog).remove();
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
for (i in data.notifications) {
|
||||
var id = 'notif_date_' + i;
|
||||
var date_cont = $('#' + id);
|
||||
if (date_cont.length === 0) {
|
||||
$notificationDialog.append('<div id="' + id + '"><div class="notification_title">' + data.notifications[i].display + '</div></div>');
|
||||
date_cont = $('#' + id);
|
||||
}
|
||||
|
||||
let j = 0;
|
||||
for (j in data.notifications[i].notifications) {
|
||||
var loc_dat = data.notifications[i].notifications[j];
|
||||
var html = '<div style="position:relative;" id="notification_' + loc_dat.id + '" class="notification">' +
|
||||
'<table style="width:100%;" cellspacing="0" cellpadding="0" border="0"><tr><td style="width:25px;">' +
|
||||
loc_dat.icon +
|
||||
'</td><td>' +
|
||||
'<div style="position:relative;" class="' + loc_dat.classname + '">' +
|
||||
loc_dat.text + ' <span class="time">' + loc_dat.time + '</span></div>' +
|
||||
'</td></tr></table>' +
|
||||
'</div>';
|
||||
date_cont.append(html);
|
||||
}
|
||||
}
|
||||
|
||||
var next_ln = $.trim(data.next);
|
||||
|
||||
if (next_ln !== '') {
|
||||
$notificationDialog.append('<div class="notification_next">' + next_ln + '</div>');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const read_notifications = () => {
|
||||
var notifications = [];
|
||||
|
||||
$('#notification_box .unread').each(function () {
|
||||
notifications.push($(this).attr('id').split('_').pop());
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/user/notifications/read/',
|
||||
data: {
|
||||
notifications: notifications.join('_')
|
||||
},
|
||||
success: function (data) {
|
||||
$('.notification_trigger .counter').css('visibility', 'hidden').empty();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const clear_notifications = () => {
|
||||
var unread = $('#notification_box .unread');
|
||||
|
||||
if (unread.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
unread.removeClass('unread');
|
||||
$('.notification_trigger .counter').css('visibility', 'hidden').empty();
|
||||
};
|
||||
|
||||
return {
|
||||
initialize,
|
||||
addNotifications
|
||||
};
|
||||
};
|
||||
|
||||
export default notifyLayout;
|
@@ -0,0 +1,46 @@
|
||||
import {Observable} from 'rx';
|
||||
// import {ajax} from 'jquery';
|
||||
import $ from 'jquery';
|
||||
let notifyService = (services) => {
|
||||
const {configService} = services;
|
||||
const url = configService.get('baseUrl');
|
||||
const notificationEndPoint = 'session/notifications/';
|
||||
let initialize = () => {
|
||||
};
|
||||
|
||||
let getNotification = (data) => {
|
||||
/*return ajax({
|
||||
type: 'POST',
|
||||
url: `${notificationEndPoint}`,
|
||||
data: data,
|
||||
dataType: 'json'
|
||||
}).promise();*/
|
||||
let notificationPromise = $.Deferred();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}${notificationEndPoint}`,
|
||||
data: data,
|
||||
dataType: 'json'
|
||||
}).done((data) => {
|
||||
data.status = data.status || false;
|
||||
if (data.status === 'ok') {
|
||||
notificationPromise.resolve(data);
|
||||
} else {
|
||||
notificationPromise.reject(data);
|
||||
}
|
||||
})
|
||||
.fail((data) => {
|
||||
notificationPromise.reject(data);
|
||||
});
|
||||
return notificationPromise.promise();
|
||||
};
|
||||
|
||||
let stream = Observable.fromPromise(getNotification);
|
||||
return {
|
||||
initialize,
|
||||
getNotification,
|
||||
stream
|
||||
};
|
||||
};
|
||||
export default notifyService;
|
257
Phraseanet-production-client/src/components/order/index.js
Normal file
257
Phraseanet-production-client/src/components/order/index.js
Normal file
@@ -0,0 +1,257 @@
|
||||
import $ from 'jquery';
|
||||
import orderItem from './orderItem';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
|
||||
const order = services => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const initialize = (options = {}) => {
|
||||
const { $container } = options;
|
||||
$container.on('click', '.order-open-action', function (event) {
|
||||
event.preventDefault();
|
||||
orderModal(event);
|
||||
});
|
||||
$container.on('click', '.order-notif', function (event) {
|
||||
event.preventDefault();
|
||||
$('#notification_box').hide();
|
||||
orderModal(event, this);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const orderModal = (event, id) => {
|
||||
var $dialog = dialog.create(services, {
|
||||
size: 'Full',
|
||||
title: $(event).attr('title')
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: `${url}prod/order/`,
|
||||
success: function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onOrderReady($dialog);
|
||||
if ($(id).length) {
|
||||
$('#order_manager').css('opacity',0).hide(function () {
|
||||
console.log($(id).data("id"));
|
||||
$('#order_' + $(id).data("id")).trigger('click');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const _onOrderReady = $dialog => {
|
||||
let filterDateSelected = false;
|
||||
let perPage = window.orderData.perPage;
|
||||
let date = window.orderData.date;
|
||||
let dateSelection = window.orderData.dateSelection;
|
||||
let dateSelectionText = window.orderData.dateSelectionText;
|
||||
let info = window.orderData.info;
|
||||
let tabSelection = window.orderData.tabSelection;
|
||||
|
||||
const FilterTodo = {
|
||||
TODO: 'pending',
|
||||
PROCESSED: 'processed'
|
||||
};
|
||||
const FilterDate = {
|
||||
NO_FILTER: 'no_filter',
|
||||
CURRENT_WEEK: 'current_week',
|
||||
PAST_WEEK: 'past_week',
|
||||
PAST_MONTH: 'past_month',
|
||||
BEFORE: 'before',
|
||||
AFTER: 'after'
|
||||
};
|
||||
|
||||
/******** functions *********/
|
||||
const setDateInPicker = date => {
|
||||
if (date !== '') {
|
||||
$('#datepicker').val(date);
|
||||
}
|
||||
};
|
||||
|
||||
const setDateSelection = element => {
|
||||
var selection = $(element).attr('name');
|
||||
dateSelection = FilterDate[selection];
|
||||
setSelectionText(dateSelection);
|
||||
clearAll();
|
||||
$(element).addClass('active');
|
||||
};
|
||||
|
||||
const setSelectionText = dateSelection => {
|
||||
if (dateSelection === undefined) {
|
||||
return;
|
||||
}
|
||||
$('.reset-btn').hide();
|
||||
if (dateSelection !== FilterDate.NO_FILTER) {
|
||||
if (
|
||||
dateSelection === FilterDate.BEFORE ||
|
||||
dateSelection === FilterDate.AFTER
|
||||
) {
|
||||
dateSelectionText =
|
||||
$(
|
||||
`#filter_box tbody tr td button[name=${dateSelection.toUpperCase()}]`
|
||||
).html() +
|
||||
' ' +
|
||||
$('#datepicker').val();
|
||||
var obj = {};
|
||||
obj.date = $('#datepicker').val();
|
||||
obj.type = dateSelection;
|
||||
info.limit = obj;
|
||||
} else {
|
||||
dateSelectionText = $(
|
||||
`#filter_box tbody tr td button[name=${dateSelection.toUpperCase()}]`
|
||||
).html();
|
||||
info.limit = null;
|
||||
}
|
||||
$('#filter-text').text(dateSelectionText);
|
||||
$('.reset-btn').show();
|
||||
} else {
|
||||
$('#filter-text').text(window.orderData.noFilterText);
|
||||
info.limit = null;
|
||||
}
|
||||
info.todo = tabSelection;
|
||||
info.start = dateSelection;
|
||||
};
|
||||
|
||||
const clearAll = () => {
|
||||
$('#filter_box tbody tr td').children('button').each(function () {
|
||||
$(this).removeClass('active');
|
||||
});
|
||||
};
|
||||
|
||||
const performRequest = () => {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '../prod/order/',
|
||||
data: info,
|
||||
success: function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onOrderReady($dialog);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const toggleFilterDate = () => {
|
||||
if (!filterDateSelected) {
|
||||
filterDateSelected = true;
|
||||
$('#filter-date').addClass('active');
|
||||
$('#filter_box').css('display', 'block');
|
||||
} else {
|
||||
filterDateSelected = false;
|
||||
$('#filter-date').removeClass('active');
|
||||
$('#filter_box').css('display', 'none');
|
||||
}
|
||||
};
|
||||
|
||||
$('#datepicker').datepicker({
|
||||
beforeShow: () => {
|
||||
setTimeout(() => {
|
||||
$('.ui-datepicker').css('z-index', 999999);
|
||||
}, 0);
|
||||
},
|
||||
changeYear: true,
|
||||
changeMonth: true,
|
||||
dateFormat: 'yy/mm/dd',
|
||||
onSelect: value => {
|
||||
date = value;
|
||||
setSelectionText(dateSelection);
|
||||
}
|
||||
});
|
||||
|
||||
$('.reset-btn', $dialog.getDomElement()).bind('click', function (e) {
|
||||
info.start = FilterDate.NO_FILTER;
|
||||
setSelectionText(FilterDate.NO_FILTER);
|
||||
$('#date-form').trigger('submit');
|
||||
});
|
||||
|
||||
$('#ORDERPREVIEW').tabs({
|
||||
activate: function (event, ui) {
|
||||
if (ui.newPanel.selector === '#PROCESSED-ORDER') {
|
||||
$('.pager-processed').show();
|
||||
$('.pager-todo').hide();
|
||||
tabSelection = FilterTodo.PROCESSED;
|
||||
} else {
|
||||
$('.pager-processed').hide();
|
||||
$('.pager-todo').show();
|
||||
tabSelection = FilterTodo.TODO;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#ORDERPREVIEW').tabs(
|
||||
'option',
|
||||
'active',
|
||||
tabSelection === FilterTodo.PROCESSED ? 1 : 0
|
||||
);
|
||||
$('.pager-processed').hide();
|
||||
|
||||
$('a.self-ajax', $dialog.getDomElement()).bind('click', function (e) {
|
||||
e.preventDefault();
|
||||
var url = $(this).attr('href');
|
||||
dialog.load(url);
|
||||
});
|
||||
|
||||
$(
|
||||
'#date-form .toggle-button-text',
|
||||
$dialog.getDomElement()
|
||||
).bind('click', function (e) {
|
||||
setDateSelection(this);
|
||||
//trigger request immediately for this week, past week, past month
|
||||
if (
|
||||
$(this).attr('name') !== 'BEFORE' &&
|
||||
$(this).attr('name') !== 'AFTER'
|
||||
) {
|
||||
$('#date-form').trigger('submit');
|
||||
}
|
||||
});
|
||||
|
||||
$('.pager li', $dialog.getDomElement()).bind('click', function (e) {
|
||||
info.todo = tabSelection;
|
||||
info.start = dateSelection;
|
||||
info['per-page'] = perPage;
|
||||
info.page = $(this).find('a').attr('data-page');
|
||||
|
||||
performRequest();
|
||||
});
|
||||
|
||||
$('tr.order_row', $dialog.getDomElement())
|
||||
.bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
let orderId = $(this).attr('id').split('_').pop();
|
||||
|
||||
orderItem(services).openModal(orderId);
|
||||
})
|
||||
.addClass('clickable');
|
||||
|
||||
$('#filter-date a').click(function () {
|
||||
toggleFilterDate();
|
||||
});
|
||||
|
||||
$('#date-form').submit(function (e) {
|
||||
e.preventDefault();
|
||||
performRequest();
|
||||
toggleFilterDate();
|
||||
});
|
||||
|
||||
setDateInPicker(date);
|
||||
setSelectionText(dateSelection);
|
||||
|
||||
if (dateSelection !== FilterDate.NO_FILTER) {
|
||||
let element = $(
|
||||
`#filter_box tbody tr td button[name='${dateSelection.toUpperCase()}]`
|
||||
);
|
||||
setDateSelection(element);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
initialize,
|
||||
orderModal
|
||||
};
|
||||
};
|
||||
|
||||
export default order;
|
938
Phraseanet-production-client/src/components/order/orderItem.js
Normal file
938
Phraseanet-production-client/src/components/order/orderItem.js
Normal file
@@ -0,0 +1,938 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import * as appCommons from './../../phraseanet-common';
|
||||
import order from './index';
|
||||
import _ from 'underscore';
|
||||
import pym from 'pym.js';
|
||||
|
||||
const orderItem = services => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
const openModal = orderId => {
|
||||
let $dialog = dialog.create(services, {
|
||||
size: 'Full'
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: `${url}prod/order/${orderId}`,
|
||||
success: function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onOrderItemReady($dialog);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const _onOrderItemReady = $dialog => {
|
||||
let userInfoIsVisible = false;
|
||||
let itemCount = 0;
|
||||
let elementsForValidation = [];
|
||||
let readyForValidation = false;
|
||||
let lastItemChosen = null;
|
||||
|
||||
const ELEMENT_TYPE = {
|
||||
VALIDATED: 'validated',
|
||||
DENIED: 'denied',
|
||||
SELECTABLE: 'selectable',
|
||||
SELECTED: 'selected',
|
||||
WAITINGFORVALIDATION: 'waitingForValidation'
|
||||
};
|
||||
|
||||
let trs = $('.order_list .order_row', $dialog.getDomElement());
|
||||
let lastSelectedRow;
|
||||
if ($('#notification_box').is(':visible')) {
|
||||
$('.notification_trigger').trigger('mousedown');
|
||||
}
|
||||
|
||||
$('.order_launcher', $dialog.getDomElement()).on('click', function (event) {
|
||||
if (readyForValidation) {
|
||||
if (confirm(window.orderItemData.translatedText.message)) {
|
||||
order(services).orderModal(event);
|
||||
}
|
||||
} else {
|
||||
order(services).orderModal(event);
|
||||
}
|
||||
});
|
||||
|
||||
$('#email-btn', $dialog.getDomElement()).on('click', function () {
|
||||
let email = window.orderItemData.userEmail;
|
||||
let subject = window.orderItemData.subject;
|
||||
let body = window.orderItemData.body;
|
||||
if (email !== null) {
|
||||
let link =
|
||||
'mailto:' +
|
||||
email +
|
||||
'?subject=' +
|
||||
encodeURIComponent(subject) +
|
||||
'&body=' +
|
||||
encodeURIComponent(body);
|
||||
window.location.href = link;
|
||||
}
|
||||
});
|
||||
|
||||
$(
|
||||
'input[name="select-all"]',
|
||||
$dialog.getDomElement()
|
||||
).bind('click', function () {
|
||||
let checkboxElement = this;
|
||||
itemCount = 0;
|
||||
let selectable = [];
|
||||
$('.table-order .order_row').each(function () {
|
||||
let el = $(this);
|
||||
if (
|
||||
checkboxElement.checked &&
|
||||
el.hasClass(ELEMENT_TYPE.SELECTABLE)
|
||||
) {
|
||||
el.addClass(ELEMENT_TYPE.SELECTED);
|
||||
itemCount++;
|
||||
selectable.push(el);
|
||||
} else {
|
||||
el.removeClass(ELEMENT_TYPE.SELECTED);
|
||||
}
|
||||
});
|
||||
//load preview for single item selected
|
||||
if (selectable.length === 1) {
|
||||
loadPreviewAndCaption(selectable[0]);
|
||||
}
|
||||
renderOrderDetailView(itemCount);
|
||||
});
|
||||
|
||||
$(
|
||||
'.order_list .order_row',
|
||||
$dialog.getDomElement()
|
||||
).bind('click', function (event) {
|
||||
let $this = $(this);
|
||||
lastItemChosen = $this;
|
||||
|
||||
//disable select all checkbox if selected
|
||||
if ($('input[name="select-all"]').is(':checked')) {
|
||||
$('input[name="select-all"]').prop('checked', false);
|
||||
}
|
||||
|
||||
if (appCommons.utilsModule.is_ctrl_key(event)) {
|
||||
if (!$this.hasClass(ELEMENT_TYPE.SELECTABLE)) {
|
||||
return;
|
||||
}
|
||||
if ($this.hasClass(ELEMENT_TYPE.SELECTED)) {
|
||||
$this.removeClass(ELEMENT_TYPE.SELECTED);
|
||||
itemCount--;
|
||||
} else {
|
||||
$this.addClass(ELEMENT_TYPE.SELECTED);
|
||||
itemCount++;
|
||||
}
|
||||
} else if (appCommons.utilsModule.is_shift_key(event)) {
|
||||
if (!$this.hasClass(ELEMENT_TYPE.SELECTABLE)) {
|
||||
return;
|
||||
}
|
||||
let currentIndex = $this.index('.order_list .order_row');
|
||||
let prevIndex = lastSelectedRow.index('.order_list .order_row');
|
||||
$(
|
||||
'.order_list .selectable.selected',
|
||||
$dialog.getDomElement()
|
||||
).removeClass(ELEMENT_TYPE.SELECTED);
|
||||
itemCount = 0;
|
||||
selectRowsBetweenIndexes([prevIndex, currentIndex]);
|
||||
} else {
|
||||
$(
|
||||
'.order_list .selectable.selected',
|
||||
$dialog.getDomElement()
|
||||
).removeClass(ELEMENT_TYPE.SELECTED);
|
||||
if ($this.hasClass(ELEMENT_TYPE.SELECTABLE)) {
|
||||
$this.addClass(ELEMENT_TYPE.SELECTED);
|
||||
lastSelectedRow = $this;
|
||||
}
|
||||
itemCount = 1;
|
||||
}
|
||||
|
||||
if (itemCount === 1) {
|
||||
let selected = $(
|
||||
'.order_list .selected',
|
||||
$dialog.getDomElement()
|
||||
);
|
||||
loadPreviewAndCaption(selected);
|
||||
}
|
||||
renderOrderDetailView(itemCount);
|
||||
});
|
||||
|
||||
function selectRowsBetweenIndexes(indexes) {
|
||||
indexes.sort(function (a, b) {
|
||||
return a - b;
|
||||
});
|
||||
for (let i = indexes[0]; i <= indexes[1]; i++) {
|
||||
if ($(trs[i]).hasClass(ELEMENT_TYPE.SELECTABLE)) {
|
||||
$(trs[i]).addClass(ELEMENT_TYPE.SELECTED);
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
'.captionTips, .captionRolloverTips, .infoTips',
|
||||
$dialog.getDomElement()
|
||||
).tooltip({
|
||||
delay: 0
|
||||
});
|
||||
$('.previewTips', $dialog.getDomElement()).tooltip({
|
||||
fixable: true
|
||||
});
|
||||
|
||||
$('button.send', $dialog.getDomElement()).bind('click', function () {
|
||||
updateValidation(ELEMENT_TYPE.VALIDATED);
|
||||
//send_documents(order_id);
|
||||
});
|
||||
|
||||
$('button.deny', $dialog.getDomElement()).bind('click', function () {
|
||||
updateValidation(ELEMENT_TYPE.DENIED);
|
||||
//deny_documents(order_id);
|
||||
});
|
||||
|
||||
$('button.reset', $dialog.getDomElement()).bind('click',function(){
|
||||
var itemsToBeReset = [];
|
||||
$('.order_list .order_row.selected.waitingForValidation', $dialog.getDomElement()).each(function(i,n){
|
||||
itemsToBeReset.push($(n));
|
||||
});
|
||||
//if item is not selected, delete item being previewed
|
||||
if(itemsToBeReset.length == 0 && lastItemChosen) {
|
||||
itemsToBeReset.push(lastItemChosen);
|
||||
}
|
||||
resetItemForValidation(itemsToBeReset);
|
||||
toggleValidationButton();
|
||||
|
||||
//$('.order_row.selected').removeClass('to_be_denied');
|
||||
//$('.order_row.selected').removeClass('to_be_validated');
|
||||
});
|
||||
|
||||
$('.force_sender', $dialog.getDomElement()).bind('click', function () {
|
||||
if (confirm(localeService.t('forceSendDocument'))) {
|
||||
//updateValidation('validated');
|
||||
let element_id = [];
|
||||
element_id.push(
|
||||
$(this)
|
||||
.closest('.order_row')
|
||||
.find('input[name=order_element_id]')
|
||||
.val()
|
||||
);
|
||||
let order_id = $('input[name=order_id]').val();
|
||||
do_send_documents(order_id, element_id, true);
|
||||
}
|
||||
});
|
||||
|
||||
$('#userInfo').hover(
|
||||
function () {
|
||||
let offset = $('#userInfo').position();
|
||||
$('#userInfoPreview').css({
|
||||
left: offset.left - $('#userInfoPreview').width() + 48,
|
||||
top: offset.top + $('#userInfo').height() + 8
|
||||
});
|
||||
$('#userInfoPreview').show();
|
||||
},
|
||||
function () {
|
||||
if (!userInfoIsVisible) {
|
||||
$('#userInfoPreview').hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$('#userInfo').click(function () {
|
||||
let offset = $('#userInfo').position();
|
||||
if (!userInfoIsVisible) {
|
||||
userInfoIsVisible = true;
|
||||
$('#userInfoPreview').css({
|
||||
left: offset.left - $('#userInfoPreview').width() + 48,
|
||||
top: offset.top + $('#userInfo').height() + 8
|
||||
});
|
||||
$('#userInfoPreview').show();
|
||||
} else {
|
||||
userInfoIsVisible = false;
|
||||
$('#userInfoPreview').hide();
|
||||
}
|
||||
});
|
||||
|
||||
let minimized_elements = $('.minimize');
|
||||
|
||||
$('.minimize').each(function () {
|
||||
let t = $(this).text();
|
||||
if (t.length < 60) return;
|
||||
|
||||
$(this).html(
|
||||
t.slice(0, 60) +
|
||||
'<span>... </span><a href="#" class="more">' +
|
||||
window.orderItemData.translatedText.moreText +
|
||||
'</a>' +
|
||||
'<span style="display:none;">' +
|
||||
t.slice(60, t.length) +
|
||||
' <a href="#" class="less">' +
|
||||
window.orderItemData.translatedText.lessText +
|
||||
'</a></span>'
|
||||
);
|
||||
});
|
||||
|
||||
$('a.more', minimized_elements).click(function (event) {
|
||||
event.preventDefault();
|
||||
$(this).hide().prev().hide();
|
||||
$(this).next().show();
|
||||
});
|
||||
|
||||
$('a.less', minimized_elements).click(function (event) {
|
||||
event.preventDefault();
|
||||
$(this).parent().hide().prev().show().prev().show();
|
||||
});
|
||||
|
||||
$('button.validate', $dialog.getDomElement()).bind('click', function (
|
||||
event
|
||||
) {
|
||||
openValidationDialog(this, event);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.basket-btn').click(function (event) {
|
||||
let titleCreate = window.orderItemData.translatedText.createTitle;
|
||||
let type = $(this).attr('type');
|
||||
var dialog_buttons = {};
|
||||
dialog_buttons[titleCreate] = function () {
|
||||
createBasket($innerDialog);
|
||||
$(this).dialog('close');
|
||||
};
|
||||
let $innerDialog = $('#basket-window')
|
||||
.dialog({
|
||||
open: function (event, ui) {
|
||||
$('.ui-dialog').css('z-index', 100000);
|
||||
$('.ui-widget-overlay').css('z-index', 100000);
|
||||
},
|
||||
closeOnEscape: true,
|
||||
width: 450,
|
||||
height: 300,
|
||||
modal: true,
|
||||
draggable: false,
|
||||
stack: false,
|
||||
title: window.orderItemData.translatedText.dialogTitle,
|
||||
overlay: {
|
||||
backgroundColor: '#000',
|
||||
opacity: 0.7
|
||||
},
|
||||
buttons: dialog_buttons
|
||||
})
|
||||
.dialog('open');
|
||||
populateBasketDialog($innerDialog, type);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#myDropdown').on('click', function () {
|
||||
if ($('#myDropdown').hasClass('open')) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
$('.order_list .selected', $dialog.getDomElement()).length > 0
|
||||
) {
|
||||
$('li[type="selected"]').removeClass('disabled');
|
||||
} else {
|
||||
//no selected item
|
||||
if (!$('li[type="selected"]').hasClass('disabled')) {
|
||||
$('li[type="selected"]').addClass('disabled');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function createBasket($innerDialog) {
|
||||
let $form = $('form', $innerDialog);
|
||||
let dialog = $innerDialog.closest('.ui-dialog');
|
||||
let buttonPanel = dialog.find('.ui-dialog-buttonpane');
|
||||
|
||||
$.ajax({
|
||||
type: $form.attr('method'),
|
||||
url: $form.attr('action'),
|
||||
data: $form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
$(
|
||||
":button:contains('" + localeService.t('create') + "')",
|
||||
buttonPanel
|
||||
)
|
||||
.attr('disabled', true)
|
||||
.addClass('ui-state-disabled');
|
||||
},
|
||||
success: function (data) {
|
||||
let order_id = $('input[name=order_id]').val();
|
||||
let success = '0';
|
||||
if (data.success) {
|
||||
success = '1';
|
||||
}
|
||||
|
||||
var url =
|
||||
'../prod/order/' +
|
||||
order_id +
|
||||
'/?success=' +
|
||||
success +
|
||||
'&action=basket' +
|
||||
'&message=' +
|
||||
encodeURIComponent(data.message);
|
||||
reloadDialog(url);
|
||||
appEvents.emit('workzone.refresh');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function populateBasketDialog($innerDialog, type) {
|
||||
let lst = [];
|
||||
let orderDialog = $innerDialog;
|
||||
//set checkbox to true and disable it
|
||||
$('input[name="lst"]', orderDialog).prop('checked', true);
|
||||
$('.checkbox', orderDialog).css('visibility', 'hidden');
|
||||
//set default name
|
||||
let name = window.orderItemData.translatedText.defaultBasketTitle;
|
||||
$('input[name="name"]', orderDialog).val(name);
|
||||
let description = window.orderItemData.description;
|
||||
let elements_ids = [];
|
||||
switch (type) {
|
||||
case 'denied':
|
||||
$(
|
||||
'.order_list .order_row.' + type,
|
||||
$dialog.getDomElement()
|
||||
).each(function (i, n) {
|
||||
elements_ids.push($(n).attr('elementids'));
|
||||
});
|
||||
break;
|
||||
case 'validated':
|
||||
$(
|
||||
'.order_list .order_row.' + type,
|
||||
$dialog.getDomElement()
|
||||
).each(function (i, n) {
|
||||
elements_ids.push($(n).attr('elementids'));
|
||||
});
|
||||
break;
|
||||
default:
|
||||
//selected elements;
|
||||
$(
|
||||
'.order_list .order_row.' + type,
|
||||
$dialog.getDomElement()
|
||||
).each(function (i, n) {
|
||||
elements_ids.push($(n).attr('elementids'));
|
||||
});
|
||||
}
|
||||
$('textarea[name="description"]', orderDialog).val(description);
|
||||
$('input[name="lst"]', orderDialog).val(elements_ids.join('; '));
|
||||
}
|
||||
|
||||
function openValidationDialog(el, event) {
|
||||
let submitTitle = window.orderItemData.translatedText.submit;
|
||||
let resetTitle = window.orderItemData.translatedText.reset;
|
||||
var dialog_buttons = {};
|
||||
dialog_buttons[submitTitle] = function () {
|
||||
//submit documents
|
||||
submitDocuments($(this));
|
||||
};
|
||||
dialog_buttons[resetTitle] = function () {
|
||||
if (confirm(window.orderItemData.translatedText.message)) {
|
||||
resetAllItemForValidation();
|
||||
toggleValidationButton();
|
||||
$(this).dialog('close');
|
||||
}
|
||||
};
|
||||
$('#validation-window')
|
||||
.dialog({
|
||||
open: function (event, ui) {
|
||||
$('.ui-dialog').css('z-index', 100000);
|
||||
$('.ui-widget-overlay').css('z-index', 100000);
|
||||
},
|
||||
closeOnEscape: true,
|
||||
resizable: false,
|
||||
width: 450,
|
||||
height: 500,
|
||||
modal: true,
|
||||
draggable: false,
|
||||
stack: false,
|
||||
title: window.orderItemData.translatedText.validation,
|
||||
buttons: dialog_buttons,
|
||||
overlay: {
|
||||
backgroundColor: '#000',
|
||||
opacity: 0.7
|
||||
}
|
||||
})
|
||||
.dialog('open');
|
||||
createValidationTable();
|
||||
}
|
||||
|
||||
function submitDocuments(dialogElem) {
|
||||
let order_id = $('input[name=order_id]').val();
|
||||
let validatedArrayNoForceIds = _.filter(
|
||||
elementsForValidation,
|
||||
function (elem) {
|
||||
return (
|
||||
elem.newState === ELEMENT_TYPE.VALIDATED &&
|
||||
elem.oldState !== ELEMENT_TYPE.DENIED
|
||||
);
|
||||
}
|
||||
).map(function (elem) {
|
||||
return elem.elementId;
|
||||
});
|
||||
|
||||
let validatedArrayWithForceIds = _.filter(
|
||||
elementsForValidation,
|
||||
function (elem) {
|
||||
return (
|
||||
elem.newState === ELEMENT_TYPE.VALIDATED &&
|
||||
elem.oldState === ELEMENT_TYPE.DENIED
|
||||
);
|
||||
}
|
||||
).map(function (elem) {
|
||||
return elem.elementId;
|
||||
});
|
||||
|
||||
let deniedArrayIds = _.filter(elementsForValidation, function (
|
||||
elem
|
||||
) {
|
||||
return elem.newState === ELEMENT_TYPE.DENIED;
|
||||
}).map(function (elem) {
|
||||
return elem.elementId;
|
||||
});
|
||||
|
||||
if (validatedArrayNoForceIds.length > 0) {
|
||||
do_send_documents(order_id, validatedArrayNoForceIds, false);
|
||||
}
|
||||
if (validatedArrayWithForceIds.length > 0) {
|
||||
do_send_documents(order_id, validatedArrayWithForceIds, true);
|
||||
}
|
||||
if (deniedArrayIds.length > 0) {
|
||||
do_deny_documents(order_id, deniedArrayIds);
|
||||
}
|
||||
dialogElem.dialog('close');
|
||||
}
|
||||
|
||||
function createValidationTable() {
|
||||
$('.validation-content').empty();
|
||||
let validatedArray = _.filter(elementsForValidation, function (
|
||||
elem
|
||||
) {
|
||||
return elem.newState === ELEMENT_TYPE.VALIDATED;
|
||||
});
|
||||
let deniedArray = _.filter(elementsForValidation, function (elem) {
|
||||
return elem.newState === ELEMENT_TYPE.DENIED;
|
||||
});
|
||||
|
||||
if (validatedArray.length > 0) {
|
||||
let html = '';
|
||||
html +=
|
||||
'<h5>' +
|
||||
window.orderItemData.translatedText.youHaveValidated +
|
||||
' ' +
|
||||
validatedArray.length +
|
||||
' ' +
|
||||
window.orderItemData.translatedText.item +
|
||||
(validatedArray.length === 1 ? '' : 's') +
|
||||
'</h5>';
|
||||
html += '<table class="validation-table">';
|
||||
_.each(validatedArray, function (elem) {
|
||||
html += '<tr>';
|
||||
html +=
|
||||
'<td width="25%" align="center">' +
|
||||
elem.elementPreview[0].outerHTML +
|
||||
'</td>';
|
||||
html +=
|
||||
'<td width="75%">' +
|
||||
elem.elementTitle[0].outerHTML +
|
||||
'</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
html += '</table>';
|
||||
$('.validation-content').append(html);
|
||||
}
|
||||
|
||||
if (deniedArray.length > 0) {
|
||||
let html = '';
|
||||
html +=
|
||||
'<h5>' +
|
||||
window.orderItemData.translatedText.youHaveDenied +
|
||||
' ' +
|
||||
deniedArray.length +
|
||||
' ' +
|
||||
window.orderItemData.translatedText.item +
|
||||
(deniedArray.length === 1 ? '' : 's') +
|
||||
'</h5>';
|
||||
html += '<table class="validation-table">';
|
||||
_.each(deniedArray, function (elem) {
|
||||
html += '<tr>';
|
||||
html +=
|
||||
'<td width="25%" align="center">' +
|
||||
elem.elementPreview[0].outerHTML +
|
||||
'</td>';
|
||||
html +=
|
||||
'<td width="75%">' +
|
||||
elem.elementTitle[0].outerHTML +
|
||||
'</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
html += '</table>';
|
||||
$('.validation-content').append(html);
|
||||
}
|
||||
}
|
||||
|
||||
function removeItemFromArray(item) {
|
||||
var elementId = item.find('input[name=order_element_id]').val();
|
||||
var found = _.where(elementsForValidation, {elementId: elementId});
|
||||
if(found.length > 0) {
|
||||
item.removeClass(ELEMENT_TYPE.WAITINGFORVALIDATION);
|
||||
//replace content or row with original content
|
||||
item[0].innerHTML = found[0].element[0].innerHTML;
|
||||
//remove from array
|
||||
elementsForValidation = _.without(elementsForValidation, found[0]);
|
||||
}
|
||||
}
|
||||
function resetItemForValidation(itemsToBeReset) {
|
||||
var elementArrayType = [];
|
||||
itemsToBeReset.forEach(function(item){
|
||||
removeItemFromArray(item);
|
||||
updateButtonStatus(item.attr('class').split(/\s+/));
|
||||
elementArrayType.push(item.attr('class').split(/\s+/));
|
||||
});
|
||||
if(elementsForValidation.length == 0) {
|
||||
readyForValidation = false;
|
||||
}
|
||||
updateButtonStatusMultiple(elementArrayType);
|
||||
toggleValidationButton();
|
||||
//disable select all checkbox if selected
|
||||
if($('input[name="select-all"]').is(':checked')){
|
||||
$('input[name="select-all"]').prop('checked', false);
|
||||
}
|
||||
}
|
||||
function resetAllItemForValidation() {
|
||||
//var dialog = p4.Dialog.get(1);
|
||||
$('.order_list .order_row', $dialog.getDomElement()).each(function(i,n){
|
||||
removeItemFromArray($(n));
|
||||
updateButtonStatus($(n).attr('class').split(/\s+/));
|
||||
});
|
||||
readyForValidation = false;
|
||||
renderOrderDetailView(0);
|
||||
}
|
||||
|
||||
function updateValidation(newState) {
|
||||
let count = 0;
|
||||
$('.order_list .order_row', $dialog.getDomElement()).each(function (
|
||||
i,
|
||||
n
|
||||
) {
|
||||
if (
|
||||
$(n).hasClass(ELEMENT_TYPE.SELECTED) &&
|
||||
!$(n).hasClass(ELEMENT_TYPE.VALIDATED) &&
|
||||
!$(n).hasClass(ELEMENT_TYPE.DENIED) &&
|
||||
!$(n).hasClass(ELEMENT_TYPE.WAITINGFORVALIDATION)
|
||||
) {
|
||||
createItemForValidation(
|
||||
$(n),
|
||||
ELEMENT_TYPE.SELECTABLE,
|
||||
newState
|
||||
);
|
||||
count++;
|
||||
} else if (
|
||||
$(n).hasClass(ELEMENT_TYPE.SELECTED) &&
|
||||
!$(n).hasClass(ELEMENT_TYPE.VALIDATED) &&
|
||||
!$(n).hasClass(ELEMENT_TYPE.WAITINGFORVALIDATION)
|
||||
) {
|
||||
createItemForValidation(
|
||||
$(n),
|
||||
ELEMENT_TYPE.DENIED,
|
||||
newState
|
||||
);
|
||||
count++;
|
||||
}
|
||||
$(n).removeClass(ELEMENT_TYPE.SELECTED);
|
||||
});
|
||||
|
||||
//if item is not selected, delete item being previewed
|
||||
if(count == 0 && lastItemChosen) {
|
||||
createItemForValidation(lastItemChosen, ELEMENT_TYPE.SELECTABLE, newState);
|
||||
count++;
|
||||
}
|
||||
|
||||
readyForValidation = true;
|
||||
toggleValidationButton();
|
||||
//disable select all checkbox if selected
|
||||
if ($('input[name="select-all"]').is(':checked')) {
|
||||
$('input[name="select-all"]').prop('checked', false);
|
||||
}
|
||||
|
||||
//multiple items selected
|
||||
if (count > 1) {
|
||||
$('#wrapper-padding').hide();
|
||||
$('.external-order-action').hide();
|
||||
$('#wrapper-multiple').hide();
|
||||
$('#wrapper-no-item').show();
|
||||
}
|
||||
}
|
||||
|
||||
function createItemForValidation(element, oldState, newState) {
|
||||
let order = {};
|
||||
order.elementTitle = element.find('span');
|
||||
order.elementPreview = element.find('.order_wrapper');
|
||||
order.elementId = element
|
||||
.find('input[name=order_element_id]')
|
||||
.val();
|
||||
order.element = element.clone(true);
|
||||
order.oldState = oldState;
|
||||
order.newState = newState;
|
||||
elementsForValidation.push(order);
|
||||
|
||||
//element.removeClass('to_be_denied');
|
||||
//element.removeClass('to_be_validated');
|
||||
|
||||
element.toggleClass(ELEMENT_TYPE.WAITINGFORVALIDATION);
|
||||
//element.addClass('to_be_'+order.newState);
|
||||
|
||||
element.find('td:first-child').empty();
|
||||
element
|
||||
.find('td:first-child')
|
||||
.append('<img style="cursor:help;" src="/assets/common/images/icons/to_be_'+order.newState+'.svg" title="">');
|
||||
updateButtonStatus(element.attr('class').split(/\s+/));
|
||||
}
|
||||
|
||||
function toggleValidationButton() {
|
||||
if (readyForValidation) {
|
||||
$('button.validate').prop('disabled', false);
|
||||
$('button.validate').css('color', '#7CD21C');
|
||||
} else {
|
||||
$('button.validate').prop('disabled', true);
|
||||
$('button.validate').css('color', '#737373');
|
||||
}
|
||||
}
|
||||
|
||||
function do_send_documents(order_id, elements_ids, force) {
|
||||
let cont = $dialog.getDomElement();
|
||||
|
||||
$('button.deny, button.send', cont).prop('disabled', true);
|
||||
$('.activity_indicator', cont).show();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '../prod/order/' + order_id + '/send/',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'elements[]': elements_ids,
|
||||
force: force ? 1 : 0
|
||||
},
|
||||
success: function (data) {
|
||||
let success = '0';
|
||||
|
||||
if (data.success) {
|
||||
success = '1';
|
||||
}
|
||||
|
||||
var url =
|
||||
'../prod/order/' +
|
||||
order_id +
|
||||
'/?success=' +
|
||||
success +
|
||||
'&action=send';
|
||||
reloadDialog(url);
|
||||
},
|
||||
error: function () {
|
||||
$('button.deny, button.send', cont).prop('disabled', false);
|
||||
$('.activity_indicator', cont).hide();
|
||||
},
|
||||
timeout: function () {
|
||||
$('button.deny, button.send', cont).prop('disabled', false);
|
||||
$('.activity_indicator', cont).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function do_deny_documents(order_id, elements_ids) {
|
||||
let cont = $dialog.getDomElement();
|
||||
$('button.deny, button.send', cont).prop('disabled', true);
|
||||
$('.activity_indicator', cont).show();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '../prod/order/' + order_id + '/deny/',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'elements[]': elements_ids
|
||||
},
|
||||
success: function (data) {
|
||||
let success = '0';
|
||||
|
||||
if (data.success) {
|
||||
success = '1';
|
||||
}
|
||||
|
||||
var url =
|
||||
'../prod/order/' +
|
||||
order_id +
|
||||
'/?success=' +
|
||||
success +
|
||||
'&action=deny';
|
||||
reloadDialog(url);
|
||||
},
|
||||
error: function () {
|
||||
$('button.deny, button.send', cont).prop('disabled', false);
|
||||
$('.activity_indicator', cont).hide();
|
||||
},
|
||||
timeout: function () {
|
||||
$('button.deny, button.send', cont).prop('disabled', false);
|
||||
$('.activity_indicator', cont).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderOrderDetailView(countSelected) {
|
||||
if (countSelected > 1) {
|
||||
$('#wrapper-padding').hide();
|
||||
$('.external-order-action').hide();
|
||||
$('#wrapper-multiple').show();
|
||||
$('#wrapper-no-item').hide();
|
||||
let elementArrayType = [];
|
||||
$(
|
||||
'.order_list .selectable.selected',
|
||||
$dialog.getDomElement()
|
||||
).each(function (i, n) {
|
||||
//elementArrayType = _.union(elementArrayType, $(n).attr('class').split(/\s+/));
|
||||
elementArrayType.push($(n).attr('class').split(/\s+/));
|
||||
});
|
||||
updateButtonStatusMultiple(elementArrayType);
|
||||
//updateButtonStatus(elementArrayType);
|
||||
} else if (countSelected === 1) {
|
||||
$('#wrapper-padding').show();
|
||||
$('.external-order-action').show();
|
||||
$('#wrapper-multiple').hide();
|
||||
$('#wrapper-no-item').hide();
|
||||
} else {
|
||||
$('#wrapper-padding').hide();
|
||||
$('.external-order-action').hide();
|
||||
$('#wrapper-multiple').hide();
|
||||
$('#wrapper-no-item').show();
|
||||
}
|
||||
$('#preview-layout-multiple .title').html(countSelected);
|
||||
}
|
||||
|
||||
function updateButtonStatusMultiple(elementArrayType) {
|
||||
$('#order-action button.deny, #order-action button.send').hide();
|
||||
let countObj = elementArrayType.reduce(
|
||||
function (m, v) {
|
||||
for (let k in m) {
|
||||
if (~v.indexOf(k)) m[k]++;
|
||||
}
|
||||
return m;
|
||||
},
|
||||
{ validated: 0, selectable: 0, waitingForValidation: 0 }
|
||||
);
|
||||
|
||||
let html = '';
|
||||
if (countObj.validated > 0) {
|
||||
html +=
|
||||
'<p>' +
|
||||
window.orderItemData.translatedText.itemsAlreadySent +
|
||||
': ' +
|
||||
countObj.validated +
|
||||
'</p>';
|
||||
}
|
||||
|
||||
if (countObj.waitingForValidation > 0) {
|
||||
html +=
|
||||
'<p>' +
|
||||
window.orderItemData.translatedText.itemsWaitingValidation +
|
||||
': ' +
|
||||
countObj.waitingForValidation +
|
||||
'</p>';
|
||||
}
|
||||
|
||||
//for the remaining items
|
||||
let remaining =
|
||||
countObj.selectable -
|
||||
(countObj.validated + countObj.waitingForValidation);
|
||||
if (remaining > 0) {
|
||||
html +=
|
||||
'<p>' +
|
||||
window.orderItemData.translatedText.nonSentItems +
|
||||
': ' +
|
||||
remaining +
|
||||
'</p>';
|
||||
$('#order-action button.deny, #order-action button.send').prop(
|
||||
'disabled',
|
||||
false
|
||||
);
|
||||
$(
|
||||
'#order-action button.deny, #order-action button.send'
|
||||
).show();
|
||||
}
|
||||
|
||||
$('#wrapper-multiple #text-content').empty();
|
||||
$('#wrapper-multiple #text-content').append(html);
|
||||
}
|
||||
|
||||
/* *
|
||||
* function to update status of send and deny button
|
||||
* params - array of type for each button selected
|
||||
*/
|
||||
function updateButtonStatus(elementArrayType) {
|
||||
if (_.contains(elementArrayType, ELEMENT_TYPE.VALIDATED)) {
|
||||
$('#order-action button.deny, #order-action button.send, #order-action button.reset').hide();
|
||||
$('#order-action span.action-text').html(
|
||||
window.orderItemData.translatedText.alreadyValidated +
|
||||
'<i class="fa fa-check" aria-hidden="true"></i>'
|
||||
);
|
||||
$('#order-action span.action-text').show();
|
||||
} else if (
|
||||
_.contains(elementArrayType, ELEMENT_TYPE.WAITINGFORVALIDATION)
|
||||
) {
|
||||
$('#order-action button.deny, #order-action button.send, #order-action span.action-text').hide();
|
||||
$('#order-action button.reset').show();
|
||||
//$('#order-action button.send').show();
|
||||
//$('#order-action button.send').prop('disabled', true);
|
||||
} else if (_.contains(elementArrayType, ELEMENT_TYPE.DENIED)) {
|
||||
$('#order-action button.deny, #order-action button.reset').hide();
|
||||
$('#order-action span.action-text').html('window.orderItemData.translatedText.refusedPreviously');
|
||||
//$('#order-action button.send').prop('disabled', false);
|
||||
$('#order-action button.send, #order-action span.action-text').show();
|
||||
} else {
|
||||
// $('#order-action button.send, #order-action button.deny').prop('disabled', false);
|
||||
$('#order-action button.send, #order-action button.deny').show();
|
||||
$('#order-action span.action-text, #order-action button.reset').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function loadPreviewAndCaption(elem) {
|
||||
$('#preview-layout').empty();
|
||||
$('#caption-layout').empty();
|
||||
updateButtonStatus(elem.attr('class').split(/\s+/));
|
||||
let elementids = elem.attr('elementids').split('_');
|
||||
let sbasId = elementids[0];
|
||||
let recordId = elementids[1];
|
||||
let prevAjax = $.ajax({
|
||||
type: 'GET',
|
||||
url: '../prod/records/record/' + sbasId + '/' + recordId + '/',
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#preview-layout').append(data.html_preview);
|
||||
$('#caption-layout').append(data.desc);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function reloadDialog(url) {
|
||||
const baseUrl = configService.get('baseUrl');
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: `${baseUrl}${url}`,
|
||||
success: function (data) {
|
||||
if (data.error) {
|
||||
return;
|
||||
}
|
||||
$dialog.setContent(data);
|
||||
_onOrderItemReady($dialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
openModal
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export default orderItem;
|
416
Phraseanet-production-client/src/components/preferences/index.js
Normal file
416
Phraseanet-production-client/src/components/preferences/index.js
Normal file
@@ -0,0 +1,416 @@
|
||||
import $ from 'jquery';
|
||||
import * as appCommons from './../../phraseanet-common';
|
||||
let highlight = require('imports-loader?$=jquery!../utils/jquery-plugins/highlight');
|
||||
let colorpicker = require('imports-loader?$=jquery!../utils/jquery-plugins/colorpicker/colorpicker');
|
||||
const preferences = services => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
const initialize = (options = {}) => {
|
||||
const { $container } = options;
|
||||
|
||||
render();
|
||||
|
||||
$container.on('change', '#ADVSRCH_FILTER_FACET', event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('facet', $el.prop('checked'));
|
||||
appEvents.emit('search.updateFacetData');
|
||||
appEvents.emit('search.doRefreshState');
|
||||
});
|
||||
|
||||
$container.on('click', '.open-preferences', event => {
|
||||
event.preventDefault();
|
||||
openModal(event);
|
||||
});
|
||||
|
||||
$container.on('click', '.preferences-options-submit', event => {
|
||||
event.preventDefault();
|
||||
submitState();
|
||||
});
|
||||
|
||||
$container.on('change', '.preferences-options-start-page', event => {
|
||||
event.preventDefault();
|
||||
setInitialStateOptions();
|
||||
});
|
||||
|
||||
$container.on('change', '.preferences-options-search-reload', event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'advanced_search_reload',
|
||||
$el.prop('checked') ? '1' : '0'
|
||||
);
|
||||
});
|
||||
|
||||
$container.on('change', '.preferences-options-use-truncation', event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'use_truncation',
|
||||
$el.prop('checked') ? '1' : '0'
|
||||
);
|
||||
});
|
||||
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-presentation-thumbnail',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('view', $el.val());
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-presentation-list',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('view', $el.val());
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-rollover-caption',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('rollover_thumbnail', $el.val());
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-rollover-preview',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('rollover_thumbnail', $el.val());
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-technical-display',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('technical_display', $el.val());
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-rollover-preview',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('technical_display', $el.val());
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-rollover-preview',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref('technical_display', $el.val());
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-doctype-display',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'doctype_display',
|
||||
$el.prop('checked') ? '1' : '0'
|
||||
);
|
||||
appEvents.emit('search.doRefreshState');
|
||||
}
|
||||
);
|
||||
|
||||
$container.on('change', '.preferences-options-basket-status', event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'basket_status_display',
|
||||
$el.prop('checked') ? '1' : '0'
|
||||
);
|
||||
});
|
||||
|
||||
$container.on(
|
||||
'change',
|
||||
'.preferences-options-basket-caption',
|
||||
event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'basket_caption_display',
|
||||
$el.prop('checked') ? '1' : '0'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$container.on('change', '.preferences-options-basket-title', event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'basket_title_display',
|
||||
$el.prop('checked') ? '1' : '0'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
$container.on('change', '.preferences-options-basket-type', event => {
|
||||
let $el = $(event.currentTarget);
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'basket_type_display',
|
||||
$el.prop('checked') ? '1' : '0'
|
||||
);
|
||||
});
|
||||
|
||||
$container.on('click', '.preference-change-theme-action', event => {
|
||||
let $el = $(event.currentTarget);
|
||||
let color = $el.data('theme');
|
||||
let minified = configService.get('debug') ? '' : '.min';
|
||||
// setCss()
|
||||
$('#skinCss').attr(
|
||||
'href',
|
||||
`/assets/production/skin-${color}${minified}.css`
|
||||
);
|
||||
|
||||
/* $.post(`${configService.get('baseUrl')}/user/preferences/`, {
|
||||
prop: 'css',
|
||||
value: color,
|
||||
t: Math.random()
|
||||
});*/
|
||||
var skin = '';
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}user/preferences/`,
|
||||
data: {
|
||||
prop: 'css',
|
||||
value: color,
|
||||
t: Math.random()
|
||||
},
|
||||
success: function (data) {
|
||||
$('body').removeClass().addClass('PNB ' + color);
|
||||
/* console.log('saved:' + color);*/
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$container.on('change', '.preferences-options-collection-order', event => {
|
||||
let el = $('#look_box_settings select[name=orderByName]');
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'order_collection_by',
|
||||
el.val()
|
||||
);
|
||||
});
|
||||
|
||||
$('.preferences-facet-order').change( function (event) {
|
||||
let el = $('.look_box_settings select[name=orderFacet]');
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'order_facet',
|
||||
el.val()
|
||||
);
|
||||
appEvents.emit('search.updateFacetData');
|
||||
});
|
||||
|
||||
$('.preferences-facet-values-order').change( function (event) {
|
||||
let el = $('.look_box_settings select[name=facetValuesOrder]');
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'facet_values_order',
|
||||
el.val()
|
||||
);
|
||||
appEvents.emit('search.updateFacetData');
|
||||
});
|
||||
|
||||
$container.on('change', '.upload-options-collection', event => {
|
||||
let el = $('.settings-box select[name=base_id]');
|
||||
event.preventDefault();
|
||||
appCommons.userModule.setPref(
|
||||
'upload_last_used_collection',
|
||||
el.val()
|
||||
);
|
||||
});
|
||||
|
||||
$('#nperpage_slider').slider({
|
||||
value: parseInt($('#nperpage_value').val(), 10),
|
||||
min: 10,
|
||||
max: 100,
|
||||
step: 10,
|
||||
slide: function (event, ui) {
|
||||
$('#nperpage_value').val(ui.value);
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
appCommons.userModule.setPref(
|
||||
'images_per_page',
|
||||
$('#nperpage_value').val()
|
||||
);
|
||||
}
|
||||
});
|
||||
$('#sizeAns_slider').slider({
|
||||
value: parseInt($('#sizeAns_value').val(), 10),
|
||||
min: 90,
|
||||
max: 270,
|
||||
step: 10,
|
||||
slide: function (event, ui) {
|
||||
$('#sizeAns_value').val(ui.value);
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
appCommons.userModule.setPref(
|
||||
'images_size',
|
||||
$('#sizeAns_value').val()
|
||||
);
|
||||
}
|
||||
});
|
||||
$('#backcolorpickerHolder').ColorPicker({
|
||||
flat: true,
|
||||
color: '404040',
|
||||
livePreview: false,
|
||||
eventName: 'mouseover',
|
||||
onSubmit: function (hsb, hex, rgb, el) {
|
||||
var back_hex = '';
|
||||
var unactive = '';
|
||||
var sim_b;
|
||||
|
||||
if (hsb.b >= 50) {
|
||||
back_hex = '000000';
|
||||
|
||||
sim_b = 0.1 * hsb.b;
|
||||
} else {
|
||||
back_hex = 'FFFFFF';
|
||||
|
||||
sim_b = 100 - 0.1 * (100 - hsb.b);
|
||||
}
|
||||
|
||||
sim_b = 0.1 * hsb.b;
|
||||
|
||||
var sim_rgb = appCommons.utilsModule.hsl2rgb(
|
||||
hsb.h,
|
||||
hsb.s,
|
||||
sim_b
|
||||
);
|
||||
var sim_hex = appCommons.utilsModule.RGBtoHex(
|
||||
sim_rgb.r,
|
||||
sim_rgb.g,
|
||||
sim_rgb.b
|
||||
);
|
||||
|
||||
appCommons.userModule.setPref('background-selection', hex);
|
||||
appCommons.userModule.setPref(
|
||||
'background-selection-disabled',
|
||||
sim_hex
|
||||
);
|
||||
appCommons.userModule.setPref('fontcolor-selection', back_hex);
|
||||
|
||||
$('style[title=color_selection]').empty();
|
||||
|
||||
var datas =
|
||||
'.diapo.selected,#reorder_box .diapo.selected, #EDIT_ALL .diapo.selected, .list.selected, .list.selected .diapo' +
|
||||
'{' +
|
||||
' COLOR: #' +
|
||||
back_hex +
|
||||
';' +
|
||||
' BACKGROUND-COLOR: #' +
|
||||
hex +
|
||||
';' +
|
||||
'}';
|
||||
$('style[title=color_selection]').empty().text(datas);
|
||||
}
|
||||
});
|
||||
$('#backcolorpickerHolder')
|
||||
.find('.colorpicker_submit')
|
||||
.append($('#backcolorpickerHolder .submiter'))
|
||||
.bind('click', function () {
|
||||
$(this).highlight('#CCCCCC');
|
||||
});
|
||||
$('#look_box .tabs').tabs();
|
||||
};
|
||||
|
||||
const render = () => {
|
||||
let availableThemes = configService.get('availableThemes');
|
||||
let themeTpl = '';
|
||||
|
||||
for (let t in availableThemes) {
|
||||
let curTheme = availableThemes[t];
|
||||
themeTpl += `<div class="colorpicker_box preference-change-theme-action" data-theme="${curTheme.name}" style="width:16px;height:16px;background-color:#${curTheme.name};"> </div>`;
|
||||
}
|
||||
// generates themes
|
||||
$('#theme-container').empty().append(themeTpl);
|
||||
};
|
||||
|
||||
// look_box
|
||||
function setInitialStateOptions() {
|
||||
var el = $('#look_box_settings select[name=start_page]');
|
||||
|
||||
switch (el.val()) {
|
||||
case 'LAST_QUERY':
|
||||
case 'PUBLI':
|
||||
case 'HELP':
|
||||
$('#look_box_settings input[name=start_page_value]').hide();
|
||||
break;
|
||||
case 'QUERY':
|
||||
$('#look_box_settings input[name=start_page_value]').show();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
function submitState() {
|
||||
var el = $('#look_box_settings select[name=start_page]');
|
||||
var val = el.val();
|
||||
|
||||
var start_page_query = $(
|
||||
'#look_box_settings input[name=start_page_value]'
|
||||
).val();
|
||||
|
||||
if (val === 'QUERY') {
|
||||
appCommons.userModule.setPref('start_page_query', start_page_query);
|
||||
}
|
||||
|
||||
appCommons.userModule.setPref('start_page', val);
|
||||
}
|
||||
|
||||
function openModal(event) {
|
||||
$('#look_box')
|
||||
.dialog({
|
||||
closeOnEscape: true,
|
||||
resizable: false,
|
||||
width: 450,
|
||||
height: 500,
|
||||
modal: true,
|
||||
draggable: false,
|
||||
overlay: {
|
||||
backgroundColor: '#000',
|
||||
opacity: 0.7
|
||||
}
|
||||
})
|
||||
.dialog('open');
|
||||
}
|
||||
|
||||
return {
|
||||
initialize,
|
||||
openModal
|
||||
};
|
||||
};
|
||||
|
||||
export default preferences;
|
454
Phraseanet-production-client/src/components/publication/index.js
Normal file
454
Phraseanet-production-client/src/components/publication/index.js
Normal file
@@ -0,0 +1,454 @@
|
||||
import $ from 'jquery';
|
||||
let lazyload = require('jquery-lazyload');
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
|
||||
const publication = (services) => {
|
||||
let ajaxState = {
|
||||
query: null,
|
||||
isRunning: false
|
||||
};
|
||||
let $answers;
|
||||
let curPage;
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const initialize = () => {
|
||||
|
||||
$answers = $('#answers');
|
||||
|
||||
// refresh current view
|
||||
$answers.on('click', '.feed_reload', function (event) {
|
||||
event.preventDefault();
|
||||
fetchPublications(curPage);
|
||||
});
|
||||
|
||||
// navigate to a specific feed
|
||||
$answers.on('click', '.ajax_answers', function (event) {
|
||||
event.preventDefault();
|
||||
var $this = $(this);
|
||||
var append = $this.hasClass('append');
|
||||
var noScroll = $this.hasClass('no_scroll');
|
||||
|
||||
_fetchRemote($(event.currentTarget).attr('href'), {})
|
||||
.then(function (data) {
|
||||
if (!append) {
|
||||
$answers.empty();
|
||||
if (!noScroll) {
|
||||
$answers.scrollTop(0);
|
||||
}
|
||||
$answers.append(data);
|
||||
|
||||
$answers.find('img.lazyload').lazyload({
|
||||
container: $answers
|
||||
});
|
||||
} else {
|
||||
$('.see_more.loading', $answers).remove();
|
||||
$answers.append(data);
|
||||
|
||||
$answers.find('img.lazyload').lazyload({
|
||||
container: $answers
|
||||
});
|
||||
|
||||
if (!noScroll) {
|
||||
$answers.animate({
|
||||
scrollTop: ($answers.scrollTop() + $answers.innerHeight() - 80)
|
||||
});
|
||||
}
|
||||
}
|
||||
appEvents.emit('search.doAfterSearch');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// subscribe_rss
|
||||
$answers.on('click', '.subscribe_rss', function (event) {
|
||||
event.preventDefault();
|
||||
let $this = $(this);
|
||||
let renew = false;
|
||||
|
||||
/*if (typeof (renew) === 'undefined') {
|
||||
renew = 'false';
|
||||
} else {
|
||||
renew = renew ? 'true' : 'false';
|
||||
}*/
|
||||
|
||||
var buttons = {};
|
||||
buttons[localeService.t('renewRss')] = function () {
|
||||
$this.trigger({
|
||||
type: 'click',
|
||||
renew: true
|
||||
});
|
||||
};
|
||||
buttons[localeService.t('fermer')] = function () {
|
||||
$('#DIALOG').empty().dialog('destroy');
|
||||
};
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $this.attr('href') + (event.renew === true ? '?renew=true' : ''),
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.texte !== false && data.titre !== false) {
|
||||
if ($('#DIALOG').data('ui-dialog')) {
|
||||
$('#DIALOG').dialog('destroy');
|
||||
}
|
||||
$('#DIALOG').attr('title', data.titre)
|
||||
.empty()
|
||||
.append(data.texte)
|
||||
.dialog({
|
||||
autoOpen: false,
|
||||
closeOnEscape: true,
|
||||
resizable: false,
|
||||
draggable: false,
|
||||
modal: true,
|
||||
buttons: buttons,
|
||||
width: 650,
|
||||
height: 250,
|
||||
overlay: {
|
||||
backgroundColor: '#000',
|
||||
opacity: 0.7
|
||||
},
|
||||
open: function() {
|
||||
$('#copy-feed').on('click', function (event) {
|
||||
event.preventDefault();
|
||||
var copyText = document.getElementById('input-select-copy');
|
||||
/* Select the text field */
|
||||
copyText.select();
|
||||
copyText.setSelectionRange(0, 99999); /*For mobile devices*/
|
||||
|
||||
document.execCommand('copy');
|
||||
});
|
||||
},
|
||||
}).dialog('open');
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// edit a feed
|
||||
$answers.on('click', '.feed .entry a.feed_edit', function () {
|
||||
var $this = $(this);
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $this.attr('href'),
|
||||
dataType: 'html',
|
||||
success: function (data) {
|
||||
return openModal(data);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// remove a feed
|
||||
$answers.on('click', '.feed .entry a.feed_delete', function () {
|
||||
if (!confirm('etes vous sur de vouloir supprimer cette entree ?')) {
|
||||
return false;
|
||||
}
|
||||
var $this = $(this);
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: $this.attr('href'),
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.error === false) {
|
||||
var $entry = $this.closest('.entry');
|
||||
$entry.animate({
|
||||
height: 0,
|
||||
opacity: 0
|
||||
}, function () {
|
||||
$entry.remove();
|
||||
});
|
||||
} else {
|
||||
alert(data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$answers.on('mouseover', '.feed .entry', function () {
|
||||
$(this).addClass('hover');
|
||||
});
|
||||
|
||||
$answers.on('mouseout', '.feed .entry', function () {
|
||||
$(this).removeClass('hover');
|
||||
});
|
||||
|
||||
$answers.on('click', '.see_more a', function (event) {
|
||||
const $see_more = $(this).closest('.see_more');
|
||||
$see_more.addClass('loading');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const _fetchRemote = function (url, data) {
|
||||
let page = 0;
|
||||
if (data.page === undefined) {
|
||||
page = data.page;
|
||||
}
|
||||
|
||||
ajaxState.query = $.ajax({
|
||||
type: 'GET',
|
||||
url: url,
|
||||
dataType: 'html',
|
||||
data: data,
|
||||
beforeSend: function () {
|
||||
if (ajaxState.isRunning && ajaxState.query.abort) {
|
||||
ajaxState.query.abort();
|
||||
}
|
||||
if (page === 0) {
|
||||
appEvents.emit('search.doClearSearch');
|
||||
}
|
||||
ajaxState.isRunning = true;
|
||||
$answers.addClass('loading');
|
||||
},
|
||||
error: function () {
|
||||
ajaxState.isRunning = false;
|
||||
$answers.removeClass('loading');
|
||||
},
|
||||
timeout: function () {
|
||||
ajaxState.isRunning = false;
|
||||
$answers.removeClass('loading');
|
||||
},
|
||||
success: function (data) {
|
||||
ajaxState.isRunning = false;
|
||||
}
|
||||
});
|
||||
return ajaxState.query;
|
||||
};
|
||||
|
||||
function checkFeedVFieldError() {
|
||||
if ($('.feed_warning').hasClass('alert-error')) {
|
||||
$('.ui-dialog-buttons').find('button').eq(1).prop('disabled', true);
|
||||
} else {
|
||||
$('.ui-dialog-buttons').find('button').eq(1).prop('disabled', false);
|
||||
}
|
||||
}
|
||||
|
||||
function feedFieldValidator (field, feedWarning , length) {
|
||||
field.on('change keyup',function () {
|
||||
if ( $(this).val().length > length){
|
||||
feedWarning.addClass('alert alert-error');
|
||||
}else {
|
||||
feedWarning.removeClass('alert alert-error');
|
||||
}
|
||||
checkFeedVFieldError();
|
||||
});
|
||||
}
|
||||
var openModal = function (data) {
|
||||
let buttons = {};
|
||||
let modal = dialog.create(services, {
|
||||
size: 'Full',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: localeService.t('Publication')
|
||||
});
|
||||
//Add custom class to dialog wrapper
|
||||
$('.dialog-Full').closest('.ui-dialog').addClass('black-dialog-wrap publish-dialog');
|
||||
|
||||
modal.setContent(data);
|
||||
|
||||
buttons[localeService.t('valider')] = onSubmitPublication;
|
||||
|
||||
modal.setOption('buttons', buttons);
|
||||
let $feeds_item = $('.feeds .feed', modal.getDomElement());
|
||||
let $form = $('form.main_form', modal.getDomElement());
|
||||
let $feed_title_field = $('#feed_add_title', modal.getDomElement());
|
||||
let $feed_title_warning = $('.feed_title_warning', modal.getDomElement());
|
||||
let $feed_subtitle_field = $('#feed_add_subtitle', modal.getDomElement());
|
||||
let $feed_subtitle_warning = $('.feed_subtitle_warning', modal.getDomElement());
|
||||
feedFieldValidator($feed_title_field,$feed_title_warning, 128);
|
||||
feedFieldValidator($feed_subtitle_field,$feed_subtitle_warning, 1024);
|
||||
|
||||
$feeds_item.bind('click', function () {
|
||||
$feeds_item.removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
$('input[name="feed_id"]', $form).val($('input', this).val());
|
||||
}).hover(function () {
|
||||
$(this).addClass('hover');
|
||||
}, function () {
|
||||
$(this).removeClass('hover');
|
||||
});
|
||||
|
||||
$form.bind('submit', function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
let formMode = 'create';
|
||||
// is edit mode?
|
||||
if ($('input[name="item_id"]').length > 0) {
|
||||
formMode = 'edit';
|
||||
}
|
||||
|
||||
$('#modal_feed .record_list').sortable({
|
||||
placeholder: 'ui-state-highlight',
|
||||
stop: function (event, ui) {
|
||||
|
||||
|
||||
var lst = [];
|
||||
$('#modal_feed .record_list .sortable form').each(function (i, el) {
|
||||
if (formMode === 'create') {
|
||||
lst.push($('input[name="sbas_id"]', el).val() + '_' + $('input[name="record_id"]', el).val());
|
||||
} else {
|
||||
lst.push($('input[name="item_id"]', el).val());
|
||||
|
||||
}
|
||||
});
|
||||
$('#modal_feed form.main_form input[name="lst"]').val(lst.join(';'));
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const onSubmitPublication = () => {
|
||||
var $dialog = dialog.get(1);
|
||||
var error = false;
|
||||
var $form = $('form.main_form', $dialog.getDomElement());
|
||||
|
||||
$('.required_text', $form).each(function (i, el) {
|
||||
if ($.trim($(el).val()) === '') {
|
||||
$(el).addClass('error');
|
||||
error = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (error) {
|
||||
alert(localeService.t('feed_require_fields'));
|
||||
}
|
||||
|
||||
if ($('input[name="feed_id"]', $form).val() === '') {
|
||||
alert(localeService.t('feed_require_feed'));
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: $form.attr('action'),
|
||||
data: $form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
$('button', $dialog.getDomElement()).prop('disabled', true);
|
||||
},
|
||||
error: function () {
|
||||
$('button', $dialog.getDomElement()).prop('disabled', false);
|
||||
},
|
||||
timeout: function () {
|
||||
$('button', $dialog.getDomElement()).prop('disabled', false);
|
||||
},
|
||||
success: function (data) {
|
||||
$('.state-navigation').trigger('click');
|
||||
$('button', $dialog.getDomElement()).prop('disabled', false);
|
||||
if (data.error === true) {
|
||||
alert(data.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($('form.main_form', $dialog.getDomElement()).hasClass('entry_update')) {
|
||||
var id = $('form input[name="entry_id"]', $dialog.getDomElement()).val();
|
||||
var container = $('#entry_' + id);
|
||||
|
||||
container.replaceWith(data.datas);
|
||||
|
||||
container.hide().fadeIn();
|
||||
|
||||
// @TODO: something was happening here
|
||||
$answers.find('img.lazyload').lazyload({
|
||||
container: $answers
|
||||
});
|
||||
}
|
||||
|
||||
$dialog.close(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var fetchPublications = function (page) {
|
||||
if (page === undefined && $answers !== undefined) {
|
||||
// @TODO $answers can be undefined
|
||||
$answers.empty();
|
||||
}
|
||||
if ($answers !== undefined) {
|
||||
curPage = page;
|
||||
return _fetchRemote(`${url}prod/feeds/`, {
|
||||
page: page
|
||||
})
|
||||
.then(function (data) {
|
||||
$('.next_publi_link', $answers).remove();
|
||||
|
||||
$answers.append(data);
|
||||
|
||||
$answers.find('img.lazyload').lazyload({
|
||||
container: $answers
|
||||
});
|
||||
|
||||
appEvents.emit('search.doAfterSearch');
|
||||
if (page > 0) {
|
||||
$answers.stop().animate({
|
||||
scrollTop: $answers.scrollTop() + $answers.height()
|
||||
}, 700);
|
||||
}
|
||||
return;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var publishRecords = function (type, value) {
|
||||
var options = {
|
||||
lst: '',
|
||||
ssel: '',
|
||||
act: ''
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case 'IMGT':
|
||||
case 'CHIM':
|
||||
options.lst = value;
|
||||
break;
|
||||
|
||||
case 'STORY':
|
||||
options.story = value;
|
||||
break;
|
||||
case 'SSTT':
|
||||
options.ssel = value;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
$.post(`${url}prod/feeds/requestavailable/`
|
||||
, options
|
||||
, function (data) {
|
||||
|
||||
return openModal(data);
|
||||
});
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const activatePublicationState = () => {
|
||||
appEvents.emit('publication.fetch');
|
||||
}
|
||||
|
||||
appEvents.listenAll({
|
||||
'publication.activeState': activatePublicationState,
|
||||
'publication.fetch': fetchPublications
|
||||
});
|
||||
return {
|
||||
initialize,
|
||||
fetchPublications,
|
||||
publishRecords,
|
||||
openModal
|
||||
};
|
||||
};
|
||||
|
||||
export default publication;
|
||||
|
@@ -0,0 +1,22 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
const addToBasket = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
let $container = null;
|
||||
const initialize = () => {
|
||||
$container = $('body');
|
||||
$container.on('click', '.record-add-to-basket-action', (event) => {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
let dbId = $el.data('db-id');
|
||||
let recordId = $el.data('record-id');
|
||||
appEvents.emit('workzone.doAddToBasket', {
|
||||
dbId, recordId, event: event.currentTarget
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return { initialize };
|
||||
};
|
||||
|
||||
export default addToBasket;
|
31
Phraseanet-production-client/src/components/record/bridge.js
Normal file
31
Phraseanet-production-client/src/components/record/bridge.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import recordBridge from './recordBridge/index';
|
||||
|
||||
const bridgeRecord = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const openModal = (datas) => {
|
||||
|
||||
const $dialog = dialog.create(services, {
|
||||
size: 'Full',
|
||||
title: 'Bridge',
|
||||
loading: false
|
||||
});
|
||||
|
||||
return $.post(`${url}prod/bridge/manager/`, datas, function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onDialogReady();
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
const _onDialogReady = () => {
|
||||
recordBridge(services).initialize();
|
||||
};
|
||||
|
||||
return { openModal };
|
||||
};
|
||||
|
||||
export default bridgeRecord;
|
185
Phraseanet-production-client/src/components/record/delete.js
Normal file
185
Phraseanet-production-client/src/components/record/delete.js
Normal file
@@ -0,0 +1,185 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
|
||||
const deleteRecord = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let workzoneSelection = [];
|
||||
let searchSelection = [];
|
||||
|
||||
const openModal = (datas) => {
|
||||
let $dialog = dialog.create(services, {
|
||||
size: '480x160',
|
||||
title: localeService.t('warning')
|
||||
});
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/records/delete/what/`,
|
||||
dataType: 'html',
|
||||
data: datas,
|
||||
success: function (data) {
|
||||
$dialog.setOption('height', 'auto');
|
||||
$dialog.setContent(data);
|
||||
|
||||
//reset top position of dialog
|
||||
$dialog.getDomElement().offsetParent().css('top', ($(window).height() - $dialog.getDomElement()[0].clientHeight) / 2);
|
||||
_onDialogReady();
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
const _onDialogReady = () => {
|
||||
var $dialog = dialog.get(1);
|
||||
var $dialogBox = $dialog.getDomElement();
|
||||
var $closeButton = $('button.ui-dialog-titlebar-close', $dialogBox.parent());
|
||||
var $cancelButton = $('button.cancel', $dialogBox);
|
||||
var $delChildren = $("input[name='del_children']", $dialogBox);
|
||||
var titleBox = $(".ui-dialog-title", $dialogBox.parent());
|
||||
titleBox.prepend('<i class="fa fa-exclamation-triangle" style="margin-right: 10px"></i>');
|
||||
|
||||
|
||||
/**
|
||||
* the checkbox "delete stories children too" changes
|
||||
**/
|
||||
$delChildren.bind("change", function () {
|
||||
fSetDelChildren($(this).is(':checked'));
|
||||
});
|
||||
|
||||
$cancelButton.bind('click', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
/**
|
||||
* set the dlg content according the "delete children" ckbox
|
||||
* the counts (records will be deleted, records rejected...) will update
|
||||
*/
|
||||
var fSetDelChildren = function (delChildren) {
|
||||
if (delChildren) {
|
||||
$("#delete_records_parent_only").hide();
|
||||
$("#delete_records_with_children").show();
|
||||
} else {
|
||||
$("#delete_records_with_children").hide();
|
||||
$("#delete_records_parent_only").show();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* click ok : run delete tasks
|
||||
*/
|
||||
$('button.submiter', $dialogBox).bind('click', function () {
|
||||
let CHUNKSIZE = 3,
|
||||
MAXTASKS = 5;
|
||||
let $this = $(this);
|
||||
let $form = $(this).closest("form"),
|
||||
$counter = $form.find(".to_delete_count"),
|
||||
$trash_counter = $form.find(".to_trash_count"),
|
||||
$loader = $form.find(".form-action-loader");
|
||||
let lst = $("input[name='lst']", $form).val().split(';');
|
||||
|
||||
/**
|
||||
* same parameters for every delete call, except the list of (CHUNKSIZE) records
|
||||
* nb: do NOT ask to delete children since they're included in lst
|
||||
*/
|
||||
let ajaxParms = {
|
||||
type: $form.attr("method"),
|
||||
url: $form.attr("action"),
|
||||
data: {
|
||||
'lst': "" // set in f
|
||||
},
|
||||
dataType: "json"
|
||||
};
|
||||
|
||||
let runningTasks = 0, // number of running tasks
|
||||
canceling = false;
|
||||
/**
|
||||
* cancel or close dlg will ask tasks to stop
|
||||
*/
|
||||
let fCancel = function () {
|
||||
$closeButton.hide();
|
||||
$cancelButton.hide();
|
||||
$loader.show();
|
||||
canceling = true;
|
||||
};
|
||||
/**
|
||||
* task fct : will loop itself while there is job to do
|
||||
*
|
||||
* @param iTask (int) The task number 0...MAXTASKS-1, usefull only to debug
|
||||
*/
|
||||
let fTask = function (iTask) {
|
||||
if (canceling) {
|
||||
return;
|
||||
}
|
||||
// pop & truncate
|
||||
ajaxParms.data.lst = lst.splice(0, CHUNKSIZE).join(';');
|
||||
$.ajax(ajaxParms)
|
||||
.success(function (data) { // prod feedback only if result ok
|
||||
$.each(data, function (i, n) {
|
||||
let imgt = $('#IMGT_' + n),
|
||||
chim = $('.CHIM_' + n),
|
||||
stories = $('.STORY_' + n);
|
||||
$('.doc_infos', imgt).remove();
|
||||
try {
|
||||
$imgt.draggable("destroy");
|
||||
} catch (e) {
|
||||
// no-op
|
||||
}
|
||||
imgt.unbind("click")
|
||||
.removeAttr("ondblclick")
|
||||
.removeClass("selected")
|
||||
.removeClass("IMGT")
|
||||
.find("img")
|
||||
.unbind();
|
||||
imgt.find(".thumb img")
|
||||
.attr("src", "/assets/common/images/icons/deleted.png")
|
||||
.css({
|
||||
width: '100%',
|
||||
height: 'auto',
|
||||
margin: '0 10px',
|
||||
top: '0'
|
||||
});
|
||||
chim.parent().slideUp().remove();
|
||||
imgt.find(".status,.title,.bottom").empty();
|
||||
|
||||
appEvents.emit('search.selection.remove', {records: n});
|
||||
|
||||
if (stories.length > 0) {
|
||||
appEvents.emit('workzone.refresh');
|
||||
} else {
|
||||
appEvents.emit('workzone.selection.remove', {records: n});
|
||||
}
|
||||
});
|
||||
})
|
||||
.then(function () { // go on even in case of error
|
||||
// countdown
|
||||
$counter.html(lst.length);
|
||||
$trash_counter.html(lst.length);
|
||||
if (lst.length === 0 || canceling) {
|
||||
// end of a task
|
||||
if (--runningTasks === 0) {
|
||||
$dialog.close();
|
||||
$('#nbrecsel').empty().append(lst.length);
|
||||
}
|
||||
} else {
|
||||
// don't recurse, give a delay to running fct to end
|
||||
window.setTimeout(fTask, 10, iTask);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// cancel or close the dlg is the same : wait
|
||||
$dialog.setOption('closeOnEscape', false);
|
||||
$closeButton.unbind("click").bind("click", fCancel);
|
||||
$cancelButton.unbind("click").bind("click", fCancel);
|
||||
// run a bunch of tasks in //
|
||||
for (runningTasks = 0; runningTasks < MAXTASKS && lst.length > 0; runningTasks++) {
|
||||
fTask(runningTasks); // pass the task his index to get nice console logs
|
||||
}
|
||||
|
||||
});
|
||||
fSetDelChildren(false);
|
||||
};
|
||||
return {openModal};
|
||||
}
|
||||
|
||||
export default deleteRecord;
|
160
Phraseanet-production-client/src/components/record/edit.js
Normal file
160
Phraseanet-production-client/src/components/record/edit.js
Normal file
@@ -0,0 +1,160 @@
|
||||
import $ from 'jquery';
|
||||
import recordEditorService from './recordEditor/index';
|
||||
import * as appCommons from './../../phraseanet-common';
|
||||
|
||||
const editRecord = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let $container = null;
|
||||
let recordEditor = recordEditorService(services);
|
||||
appEvents.listenAll({
|
||||
'record.doEdit': _doEdit
|
||||
});
|
||||
|
||||
const initialize = () => {
|
||||
|
||||
|
||||
$container = $('body');
|
||||
$container.on('click', '.edit-record-action', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
let type = '';
|
||||
let kind = $el.data('kind');
|
||||
let idContent = $el.data('id');
|
||||
|
||||
switch (kind) {
|
||||
case 'basket':
|
||||
type = 'SSTT';
|
||||
break;
|
||||
case 'record':
|
||||
type = 'IMGT';
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
_doEdit({type: type, value: idContent});
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
const openModal = (datas) => {
|
||||
$('#EDITWINDOW').empty().addClass('loading');
|
||||
//commonModule.showOverlay(2);
|
||||
|
||||
$('#EDITWINDOW').show();
|
||||
|
||||
$.ajax({
|
||||
url: `${url}prod/records/edit/`,
|
||||
type: 'POST',
|
||||
dataType: 'html',
|
||||
data: datas,
|
||||
success: (data) => {
|
||||
$('#EDITWINDOW').removeClass('loading').empty().html(data);
|
||||
// let recordEditor = recordEditorService(services);
|
||||
recordEditor.initialize({
|
||||
$container: $('#EDITWINDOW'),
|
||||
recordConfig: window.recordEditorConfig
|
||||
});
|
||||
|
||||
$('#tooltip').hide();
|
||||
return;
|
||||
},
|
||||
error: function (XHR, textStatus, errorThrown) {
|
||||
if (XHR.status === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// open Modal
|
||||
function _doEdit(options) {
|
||||
let {type, value} = options;
|
||||
var datas = {
|
||||
lst: '',
|
||||
ssel: '',
|
||||
act: ''
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case 'IMGT':
|
||||
datas.lst = value;
|
||||
break;
|
||||
|
||||
case 'SSTT':
|
||||
datas.ssel = value;
|
||||
break;
|
||||
|
||||
case 'STORY':
|
||||
datas.story = value;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return openModal(datas);
|
||||
}
|
||||
|
||||
const onGlobalKeydown = (event, specialKeyState) => {
|
||||
if (specialKeyState === undefined) {
|
||||
let specialKeyState = {
|
||||
isCancelKey: false,
|
||||
isShortcutKey: false
|
||||
};
|
||||
}
|
||||
switch (event.keyCode) {
|
||||
case 9: // tab ou shift-tab
|
||||
fieldNavigate(
|
||||
event,
|
||||
appCommons.utilsModule.is_shift_key(event) ? -1 : 1
|
||||
);
|
||||
specialKeyState.isCancelKey = specialKeyState.isShortcutKey = true;
|
||||
break;
|
||||
case 27:
|
||||
cancelChanges({ event });
|
||||
specialKeyState.isShortcutKey = true;
|
||||
break;
|
||||
|
||||
case 33: // pg up
|
||||
if (
|
||||
!options.textareaIsDirty ||
|
||||
validateFieldChanges(event, 'ask_ok')
|
||||
) {
|
||||
skipImage(event, 1);
|
||||
}
|
||||
specialKeyState.isCancelKey = true;
|
||||
break;
|
||||
case 34: // pg dn
|
||||
if (
|
||||
!options.textareaIsDirty ||
|
||||
validateFieldChanges(event, 'ask_ok')
|
||||
) {
|
||||
skipImage(event, -1);
|
||||
}
|
||||
specialKeyState.isCancelKey = true;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return specialKeyState;
|
||||
};
|
||||
|
||||
function fieldNavigate(evt, dir) {
|
||||
let current_field = $('#divS .edit_field.active');
|
||||
if (current_field.length === 0) {
|
||||
current_field = $('#divS .edit_field:first');
|
||||
current_field.trigger('click');
|
||||
} else {
|
||||
if (dir >= 0) {
|
||||
current_field.next().trigger('click');
|
||||
} else {
|
||||
current_field.prev().trigger('click');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { initialize, openModal, onGlobalKeydown };
|
||||
};
|
||||
|
||||
export default editRecord;
|
464
Phraseanet-production-client/src/components/record/export.js
Normal file
464
Phraseanet-production-client/src/components/record/export.js
Normal file
@@ -0,0 +1,464 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
const humane = require('humane-js');
|
||||
|
||||
const exportRecord = services => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let $container = null;
|
||||
const initialize = () => {
|
||||
$container = $('body');
|
||||
$container.on('click', '.record-export-action', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
let key = '';
|
||||
let kind = $el.data('kind');
|
||||
let idContent = $el.data('id');
|
||||
|
||||
switch (kind) {
|
||||
case 'basket':
|
||||
key = 'ssel';
|
||||
break;
|
||||
case 'record':
|
||||
key = 'lst';
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
doExport(`${key}=${idContent}`);
|
||||
});
|
||||
};
|
||||
|
||||
const openModal = datas => doExport(datas);
|
||||
|
||||
function doExport(datas) {
|
||||
var $dialog = dialog.create(services, {
|
||||
size: 'Medium',
|
||||
title: localeService.t('export')
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: `${url}prod/export/multi-export/`,
|
||||
data: datas,
|
||||
success: function (data) {
|
||||
$dialog.setContent(data);
|
||||
if (window.exportConfig.isGuest) {
|
||||
dialog.get(1).close();
|
||||
let guestModal = dialog.create(
|
||||
{
|
||||
size: '500x100',
|
||||
closeOnEscape: true,
|
||||
closeButton: false,
|
||||
title: window.exportConfig.msg.modalTile
|
||||
},
|
||||
2
|
||||
);
|
||||
guestModal.setContent(window.exportConfig.msg.modalContent);
|
||||
} else {
|
||||
_onExportReady($dialog, window.exportConfig);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const _onExportReady = ($dialog, dataConfig) => {
|
||||
$('.tabs', $dialog.getDomElement()).tabs();
|
||||
|
||||
$('.close_button', $dialog.getDomElement()).bind('click', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
var tabs = $('.tabs', $dialog.getDomElement());
|
||||
|
||||
if (dataConfig.haveFtp === true) {
|
||||
$('#ftp_form_selector')
|
||||
.bind('change', function () {
|
||||
$('#ftp .ftp_form').hide();
|
||||
$('#ftp .ftp_form_' + $(this).val()).show();
|
||||
$('.ftp_folder_check', dialog.get(1).getDomElement())
|
||||
.unbind('change')
|
||||
.bind('change', function () {
|
||||
if ($(this).prop('checked')) {
|
||||
$(this).next().prop('disabled', false);
|
||||
} else {
|
||||
$(this).next().prop('disabled', true);
|
||||
}
|
||||
});
|
||||
})
|
||||
.trigger('change');
|
||||
}
|
||||
|
||||
$('a.TOUview').bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
var options = {
|
||||
size: 'Medium',
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.termOfUseTitle
|
||||
};
|
||||
|
||||
let termOfuseDialog = dialog.create(services, options, 2);
|
||||
|
||||
$.get($el.attr('href'), function (content) {
|
||||
termOfuseDialog.setContent(content);
|
||||
});
|
||||
});
|
||||
|
||||
$('.close_button').bind('click', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
$('#download .download_button').bind('click', function () {
|
||||
if (!check_subdefs($('#download'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_TOU($('#download'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var total = 0;
|
||||
var count = 0;
|
||||
|
||||
$('input[name="obj[]"]', $('#download')).each(function () {
|
||||
var total_el = $(
|
||||
'#download input[name=download_' + $(this).val() + ']'
|
||||
);
|
||||
var count_el = $(
|
||||
'#download input[name=count_' + $(this).val() + ']'
|
||||
);
|
||||
if ($(this).prop('checked')) {
|
||||
total += parseInt($(total_el).val(), 10);
|
||||
count += parseInt($(count_el).val(), 10);
|
||||
}
|
||||
});
|
||||
|
||||
if (count > 1 && total / 1024 / 1024 > dataConfig.maxDownload) {
|
||||
if (
|
||||
confirm(
|
||||
`${dataConfig.msg.fileTooLarge} \n ${dataConfig.msg
|
||||
.fileTooLargeAlt}`
|
||||
)
|
||||
) {
|
||||
$(
|
||||
'input[name="obj[]"]:checked',
|
||||
$('#download')
|
||||
).each(function (i, n) {
|
||||
$(
|
||||
'input[name="obj[]"][value="' + $(n).val() + '"]',
|
||||
$('#sendmail')
|
||||
).prop('checked', true);
|
||||
});
|
||||
|
||||
$(document).find('input[name="taglistdestmail"]').tagsinput('add', dataConfig.user.email);
|
||||
|
||||
var tabs = $('.tabs', $dialog.getDomElement());
|
||||
tabs.tabs('option', 'active', 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
$('#download form').submit();
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
$('#order .order_button').bind('click', function () {
|
||||
let title = '';
|
||||
if (!check_TOU($('#order'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#order .order_button_loader').css('visibility', 'visible');
|
||||
|
||||
var options = $('#order form').serialize();
|
||||
|
||||
var $this = $(this);
|
||||
$this.prop('disabled', true).addClass('disabled');
|
||||
$.post(
|
||||
`${url}prod/order/`,
|
||||
options,
|
||||
function (data) {
|
||||
$this.prop('disabled', false).removeClass('disabled');
|
||||
|
||||
$('#order .order_button_loader').css(
|
||||
'visibility',
|
||||
'hidden'
|
||||
);
|
||||
|
||||
if (!data.error) {
|
||||
title = dataConfig.msg.success;
|
||||
} else {
|
||||
title = dataConfig.msg.warning;
|
||||
}
|
||||
|
||||
var options = {
|
||||
size: 'Alert',
|
||||
closeButton: true,
|
||||
title: title
|
||||
};
|
||||
|
||||
dialog.create(services, options, 2).setContent(data.msg);
|
||||
|
||||
if (!data.error) {
|
||||
humane.info(data.msg);
|
||||
$dialog.close();
|
||||
} else {
|
||||
humane.error(data.msg);
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
'json'
|
||||
);
|
||||
});
|
||||
|
||||
$('#ftp .ftp_button').bind('click', function () {
|
||||
if (!check_subdefs($('#ftp'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_TOU($('#ftp'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#ftp .ftp_button_loader').show();
|
||||
|
||||
$('#ftp .ftp_form:hidden').remove();
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
var options_addr = $('#ftp_form_stock form:visible').serialize();
|
||||
var options_join = $('#ftp_joined').serialize();
|
||||
|
||||
$this.prop('disabled', true);
|
||||
$.post(
|
||||
`${url}prod/export/ftp/`,
|
||||
options_addr + '&' + options_join,
|
||||
function (data) {
|
||||
$this.prop('disabled', false);
|
||||
$('#ftp .ftp_button_loader').hide();
|
||||
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
$dialog.close();
|
||||
} else {
|
||||
var alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(data.message);
|
||||
}
|
||||
return;
|
||||
},
|
||||
'json'
|
||||
);
|
||||
});
|
||||
|
||||
$('#ftp .tryftp_button').bind('click', function () {
|
||||
$('#ftp .tryftp_button_loader').css('visibility', 'visible');
|
||||
var $this = $(this);
|
||||
$this.prop('disabled', true);
|
||||
var options_addr = $('#ftp_form_stock form:visible').serialize();
|
||||
|
||||
$.post(
|
||||
`${url}prod/export/ftp/test/`,
|
||||
// no need to include 'ftp_joined' checkboxes to test ftp
|
||||
options_addr,
|
||||
function (data) {
|
||||
$('#ftp .tryftp_button_loader').css('visibility', 'hidden');
|
||||
|
||||
var options = {
|
||||
size: 'Alert',
|
||||
closeButton: true,
|
||||
title: data.success
|
||||
? dataConfig.msg.success
|
||||
: dataConfig.msg.warning
|
||||
};
|
||||
|
||||
dialog
|
||||
.create(services, options, 3)
|
||||
.setContent(data.message);
|
||||
|
||||
$this.prop('disabled', false);
|
||||
|
||||
return;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('#sendmail .sendmail_button').bind('click', function () {
|
||||
if(!validEmail($('input[name="taglistdestmail"]', $('#sendmail')).val(), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_subdefs($('#sendmail'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_TOU($('#sendmail'), dataConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($('iframe[name=""]').length === 0) {
|
||||
$('body').append(
|
||||
'<iframe style="display:none;" name="sendmail_target"></iframe>'
|
||||
);
|
||||
}
|
||||
|
||||
$('#sendmail form').submit();
|
||||
humane.infoLarge($('#export-send-mail-notif').val());
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
$('.datepicker', $dialog.getDomElement()).datepicker({
|
||||
changeYear: true,
|
||||
changeMonth: true,
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
|
||||
$(
|
||||
'a.undisposable_link',
|
||||
$dialog.getDomElement()
|
||||
).bind('click', function () {
|
||||
$(this).parent().parent().find('.undisposable').slideToggle();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(
|
||||
'input[name="obj[]"]',
|
||||
$('#download, #sendmail, #ftp')
|
||||
).bind('change', function () {
|
||||
var $form = $(this).closest('form');
|
||||
|
||||
if ($('input.caption[name="obj[]"]:checked', $form).length > 0) {
|
||||
$('div.businessfields', $form).show();
|
||||
} else {
|
||||
$('div.businessfields', $form).hide();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function validateEmail(email) {
|
||||
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(email);
|
||||
}
|
||||
|
||||
function validEmail(emailList, dataConfig) {
|
||||
//split emailList by ; , or whitespace and filter empty element
|
||||
let emails = emailList.split(/[ ,;]+/).filter(Boolean);
|
||||
let alert;
|
||||
for(let i=0; i < emails.length; i++) {
|
||||
if (!validateEmail(emails[i])) {
|
||||
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.invalidEmail);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function check_TOU(container, dataConfig) {
|
||||
let checkbox = $('input[name="TOU_accept"]', $(container));
|
||||
let go = checkbox.length === 0 || checkbox.prop('checked');
|
||||
let alert;
|
||||
if (!go) {
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Small',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.termOfUseAgree);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function check_subdefs(container, dataConfig) {
|
||||
let go = false;
|
||||
let required = false;
|
||||
let alert;
|
||||
|
||||
$('input[name="obj[]"]', $(container)).each(function () {
|
||||
if ($(this).prop('checked')) {
|
||||
go = true;
|
||||
}
|
||||
});
|
||||
|
||||
$('input.required, textarea.required', container).each(function (i, n) {
|
||||
if ($.trim($(n).val()) === '') {
|
||||
required = true;
|
||||
$(n).addClass('error');
|
||||
} else {
|
||||
$(n).removeClass('error');
|
||||
}
|
||||
});
|
||||
|
||||
if (required) {
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.requiredFields);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!go) {
|
||||
alert = dialog.create(
|
||||
services,
|
||||
{
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
title: dataConfig.msg.warning
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
alert.setContent(dataConfig.msg.missingSubdef);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return { initialize, openModal };
|
||||
};
|
||||
|
||||
export default exportRecord;
|
@@ -0,0 +1,44 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import pushRecord from './recordPush/index';
|
||||
|
||||
const recordFeedbackModal = (services, datas) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
|
||||
const openModal = (datas) => {
|
||||
/* disable push closeonescape as an over dialog may exist (add user) */
|
||||
let $dialog = dialog.create(services, {
|
||||
size: 'Full',
|
||||
title: localeService.t('feedback')
|
||||
});
|
||||
|
||||
$dialog.getDomElement().closest('.ui-dialog').addClass('feedback_dialog_container');
|
||||
|
||||
$.post(`${url}prod/push/validateform/`, datas, function (data) {
|
||||
// data content's javascript can't be fully refactored
|
||||
$dialog.setContent(data);
|
||||
_onDialogReady();
|
||||
return;
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const _onDialogReady = () => {
|
||||
pushRecord(services).initialize({
|
||||
feedback: {
|
||||
containerId: '#PushBox',
|
||||
context: 'Feedback'
|
||||
},
|
||||
listManager: {
|
||||
containerId: '#ListManager'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return { openModal };
|
||||
};
|
||||
|
||||
export default recordFeedbackModal;
|
40
Phraseanet-production-client/src/components/record/index.js
Normal file
40
Phraseanet-production-client/src/components/record/index.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import {Observable} from 'rx';
|
||||
// import {ajax} from 'jquery';
|
||||
import $ from 'jquery';
|
||||
|
||||
let recordService = (services) => {
|
||||
const {configService} = services;
|
||||
const url = configService.get('baseUrl');
|
||||
const notificationEndPoint = 'session/notifications/';
|
||||
let initialize = () => {
|
||||
};
|
||||
|
||||
let getNotification = (data) => {
|
||||
let notificationPromise = $.Deferred();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}${notificationEndPoint}`,
|
||||
data: data,
|
||||
dataType: 'json'
|
||||
}).done((data) => {
|
||||
data.status = data.status || false;
|
||||
if (data.status === 'ok') {
|
||||
notificationPromise.resolve(data);
|
||||
} else {
|
||||
notificationPromise.reject(data);
|
||||
}
|
||||
})
|
||||
.fail((data) => {
|
||||
notificationPromise.reject(data);
|
||||
});
|
||||
return notificationPromise.promise();
|
||||
};
|
||||
|
||||
let stream = Observable.fromPromise(getNotification);
|
||||
return {
|
||||
initialize,
|
||||
getNotification,
|
||||
stream
|
||||
};
|
||||
};
|
||||
export default recordService;
|
@@ -0,0 +1,449 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
function checkVocabId(VocabularyId) {
|
||||
if (typeof VocabularyId === 'undefined') {
|
||||
VocabularyId = null;
|
||||
}
|
||||
|
||||
if (VocabularyId === '') {
|
||||
VocabularyId = null;
|
||||
}
|
||||
|
||||
return VocabularyId;
|
||||
}
|
||||
|
||||
var recordFieldValue = function (meta_id, value, VocabularyId) {
|
||||
|
||||
VocabularyId = checkVocabId(VocabularyId);
|
||||
|
||||
this.datas = {
|
||||
meta_id: meta_id,
|
||||
value: value,
|
||||
VocabularyId: VocabularyId
|
||||
};
|
||||
|
||||
var $this = this;
|
||||
};
|
||||
|
||||
recordFieldValue.prototype = {
|
||||
getValue: function () {
|
||||
return this.datas.value;
|
||||
},
|
||||
getMetaId: function () {
|
||||
return this.datas.meta_id;
|
||||
},
|
||||
getVocabularyId: function () {
|
||||
return this.datas.VocabularyId;
|
||||
},
|
||||
setValue: function (value, VocabularyId) {
|
||||
|
||||
this.datas.value = value;
|
||||
this.datas.VocabularyId = checkVocabId(VocabularyId);
|
||||
return this;
|
||||
},
|
||||
remove: function () {
|
||||
this.datas.value = '';
|
||||
this.datas.VocabularyId = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
var databoxField = function (name, label, meta_struct_id, options) {
|
||||
|
||||
var defaults = {
|
||||
multi: false,
|
||||
required: false,
|
||||
readonly: false,
|
||||
maxLength: null,
|
||||
minLength: null,
|
||||
type: 'string',
|
||||
separator: null,
|
||||
vocabularyControl: null,
|
||||
vocabularyRestricted: false
|
||||
};
|
||||
|
||||
options = (typeof options === 'object') ? options : {};
|
||||
|
||||
if (isNaN(meta_struct_id)) {
|
||||
throw 'meta_struct_id should be a number';
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
this.label = label;
|
||||
this.meta_struct_id = meta_struct_id;
|
||||
this.options = $.extend(defaults, options);
|
||||
|
||||
if (this.options.multi === true && this.options.separator === null) {
|
||||
this.options.separator = ';';
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
databoxField.prototype = {
|
||||
getMetaStructId: function () {
|
||||
return this.meta_struct_id;
|
||||
},
|
||||
getName: function () {
|
||||
return this.name;
|
||||
},
|
||||
getLabel: function () {
|
||||
return this.label;
|
||||
},
|
||||
isMulti: function () {
|
||||
return this.options.multi;
|
||||
},
|
||||
isRequired: function () {
|
||||
return this.options.required;
|
||||
},
|
||||
isReadonly: function () {
|
||||
return this.options.readonly;
|
||||
},
|
||||
getMaxLength: function () {
|
||||
return this.options.maxLength;
|
||||
},
|
||||
getMinLength: function () {
|
||||
return this.options.minLength;
|
||||
},
|
||||
getType: function () {
|
||||
return this.options.type;
|
||||
},
|
||||
getSeparator: function () {
|
||||
return this.options.separator;
|
||||
}
|
||||
};
|
||||
|
||||
var recordField = function (databoxField, arrayValues) {
|
||||
|
||||
this.databoxField = databoxField;
|
||||
this.options = {
|
||||
dirty: false
|
||||
};
|
||||
this.datas = [];
|
||||
|
||||
if (arrayValues instanceof Array) {
|
||||
if (arrayValues.length > 1 && !databoxField.isMulti()) {
|
||||
throw 'You can not add multiple values to a non multi field ' + databoxField.getName();
|
||||
}
|
||||
|
||||
var first = true;
|
||||
|
||||
for (let v in arrayValues) {
|
||||
if (typeof arrayValues[v] !== 'object') {
|
||||
if (window.console) {
|
||||
console.error('Trying to add a non-recordFieldValue to the field...');
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isNaN(arrayValues[v].getMetaId())) {
|
||||
if (window.console) {
|
||||
console.error('Trying to add a recordFieldValue without metaId...');
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!first && this.options.multi === false) {
|
||||
if (window.console) {
|
||||
console.error('Trying to add multi values in a non-multi field');
|
||||
}
|
||||
}
|
||||
|
||||
/*if (window.console) {
|
||||
console.log('adding a value : ', arrayValues[v]);
|
||||
}*/
|
||||
|
||||
this.datas.push(arrayValues[v]);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
var $this = this;
|
||||
};
|
||||
recordField.prototype = {
|
||||
getName: function () {
|
||||
return this.databoxField.getName();
|
||||
},
|
||||
getMetaStructId: function () {
|
||||
return this.databoxField.getMetaStructId();
|
||||
},
|
||||
isMulti: function () {
|
||||
return this.databoxField.isMulti();
|
||||
},
|
||||
isRequired: function () {
|
||||
return this.databoxField.isRequired();
|
||||
},
|
||||
isDirty: function () {
|
||||
return this.options.dirty;
|
||||
},
|
||||
addValue: function (value, merge, VocabularyId) {
|
||||
|
||||
VocabularyId = checkVocabId(VocabularyId);
|
||||
|
||||
merge = !!merge;
|
||||
|
||||
/* if (this.databoxField.isReadonly()) {
|
||||
if (window.console) {
|
||||
console.error('Unable to set a value to a readonly field');
|
||||
}
|
||||
|
||||
return this;
|
||||
}*/
|
||||
|
||||
if (window.console) {
|
||||
console.log('adding value ', value, ' vocId : ', VocabularyId, ' ; merge is ', merge);
|
||||
}
|
||||
|
||||
if (this.isMulti()) {
|
||||
if (!this.hasValue(value, VocabularyId)) {
|
||||
if (window.console) {
|
||||
console.log('adding new multi value ', value);
|
||||
}
|
||||
this.datas.push(new recordFieldValue(null, value, VocabularyId));
|
||||
this.options.dirty = true;
|
||||
} else {
|
||||
if (window.console) {
|
||||
console.log('already have ', value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (merge === true && this.isEmpty() === false && VocabularyId === null) {
|
||||
if (window.console) {
|
||||
console.log('Merging value ', value);
|
||||
}
|
||||
this.datas[0].setValue(this.datas[0].getValue() + ' ' + value, VocabularyId);
|
||||
|
||||
this.options.dirty = true;
|
||||
} else {
|
||||
if (merge === true && this.isEmpty() === false && VocabularyId !== null) {
|
||||
if (window.console) {
|
||||
console.error('Cannot merge vocabularies');
|
||||
}
|
||||
this.datas[0].setValue(value, VocabularyId);
|
||||
} else {
|
||||
|
||||
if (!this.hasValue(value, VocabularyId)) {
|
||||
if (this.datas.length === 0) {
|
||||
/*if (window.console) {
|
||||
console.log('Adding new value ', value);
|
||||
}*/
|
||||
this.datas.push(new recordFieldValue(null, value, VocabularyId));
|
||||
} else {
|
||||
if (window.console) {
|
||||
console.log('Updating value ', value);
|
||||
}
|
||||
this.datas[0].setValue(value, VocabularyId);
|
||||
}
|
||||
this.options.dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
hasValue: function (value, VocabularyId) {
|
||||
|
||||
if (typeof value === 'undefined') {
|
||||
if (window.console) {
|
||||
console.error('Trying to check the presence of an undefined value');
|
||||
}
|
||||
}
|
||||
|
||||
VocabularyId = checkVocabId(VocabularyId);
|
||||
|
||||
for (let d in this.datas) {
|
||||
if (VocabularyId !== null) {
|
||||
if (this.datas[d].getVocabularyId() === VocabularyId) {
|
||||
if (window.console) {
|
||||
console.log('already got the vocab ID');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (this.datas[d].getVocabularyId() === null && this.datas[d].getValue() === value) {
|
||||
if (window.console) {
|
||||
console.log('already got this value');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
removeValue: function (value, vocabularyId) {
|
||||
|
||||
if (this.databoxField.isReadonly()) {
|
||||
if (window.console) {
|
||||
console.error('Unable to set a value to a readonly field');
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
vocabularyId = checkVocabId(vocabularyId);
|
||||
|
||||
if (window.console) {
|
||||
console.log('Try to remove value ', value, vocabularyId, this.datas);
|
||||
}
|
||||
|
||||
for (let d in this.datas) {
|
||||
if (window.console) {
|
||||
console.log('loopin... ', this.datas[d].getValue());
|
||||
}
|
||||
if (this.datas[d].getVocabularyId() !== null) {
|
||||
if (this.datas[d].getVocabularyId() === vocabularyId) {
|
||||
if (window.console) {
|
||||
console.log('Found within the vocab ! removing... ');
|
||||
}
|
||||
this.datas[d].remove();
|
||||
this.options.dirty = true;
|
||||
}
|
||||
} else if (this.datas[d].getValue() === value) {
|
||||
if (window.console) {
|
||||
console.log('Found ! removing... ');
|
||||
}
|
||||
this.datas[d].remove();
|
||||
this.options.dirty = true;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
isEmpty: function () {
|
||||
var empty = true;
|
||||
|
||||
for (let d in this.datas) {
|
||||
if (this.datas[d].getValue() !== '') {
|
||||
empty = false;
|
||||
}
|
||||
}
|
||||
return empty;
|
||||
},
|
||||
empty: function () {
|
||||
|
||||
if (this.databoxField.isReadonly()) {
|
||||
if (window.console) {
|
||||
console.error('Unable to set a value to a readonly field');
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
for (let d in this.datas) {
|
||||
this.datas[d].remove();
|
||||
this.options.dirty = true;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
getValue: function () {
|
||||
|
||||
if (this.isMulti()) {
|
||||
throw 'This field is multi, I can not give you a single value';
|
||||
}
|
||||
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.datas[0];
|
||||
},
|
||||
getValues: function () {
|
||||
|
||||
if (!this.isMulti()) {
|
||||
throw 'This field is not multi, I can not give you multiple values';
|
||||
}
|
||||
|
||||
if (this.isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var arrayValues = [];
|
||||
|
||||
for (let d in this.datas) {
|
||||
if (this.datas[d].getValue() === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
arrayValues.push(this.datas[d]);
|
||||
}
|
||||
|
||||
return arrayValues;
|
||||
},
|
||||
sort: function (algo) {
|
||||
this.datas.sort(algo);
|
||||
|
||||
return this;
|
||||
},
|
||||
getSerializedValues: function () {
|
||||
|
||||
var arrayValues = [];
|
||||
var values = this.getValues();
|
||||
|
||||
for (let v in values) {
|
||||
arrayValues.push(values[v].getValue());
|
||||
}
|
||||
|
||||
return arrayValues.join(' ; ');
|
||||
},
|
||||
replaceValue: function (search, replace) {
|
||||
|
||||
if (this.databoxField.isReadonly()) {
|
||||
if (window.console) {
|
||||
console.error('Unable to set a value to a readonly field');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
var n = 0;
|
||||
|
||||
for (let d in this.datas) {
|
||||
if (this.datas[d].getVocabularyId() !== null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var value = this.datas[d].getValue();
|
||||
var replacedValue = value.replace(search, replace);
|
||||
|
||||
if (value === replacedValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
n++;
|
||||
|
||||
this.removeValue(value);
|
||||
|
||||
if (!this.hasValue(replacedValue)) {
|
||||
this.addValue(replacedValue);
|
||||
}
|
||||
|
||||
this.options.dirty = true;
|
||||
}
|
||||
|
||||
return n;
|
||||
},
|
||||
exportDatas: function () {
|
||||
|
||||
var returnValue = [];
|
||||
|
||||
for (let d in this.datas) {
|
||||
var temp = {
|
||||
meta_id: this.datas[d].getMetaId() ? this.datas[d].getMetaId() : '',
|
||||
meta_struct_id: this.getMetaStructId(),
|
||||
value: this.datas[d].getValue()
|
||||
};
|
||||
|
||||
if (this.datas[d].getVocabularyId()) {
|
||||
temp.vocabularyId = this.datas[d].getVocabularyId();
|
||||
}
|
||||
returnValue.push(temp);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
databoxField, recordFieldValue, recordField
|
||||
};
|
||||
|
104
Phraseanet-production-client/src/components/record/move.js
Normal file
104
Phraseanet-production-client/src/components/record/move.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
const humane = require('humane-js');
|
||||
|
||||
let $dialog = null;
|
||||
|
||||
const moveRecord = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const openModal = (datas) => {
|
||||
$dialog = dialog.create(services, {
|
||||
size: 'Small phrasea-black-dialog',
|
||||
title: localeService.t('move'),
|
||||
closeButton: true,
|
||||
});
|
||||
//Add custom class to dialog wrapper
|
||||
$('.phrasea-black-dialog').closest('.ui-dialog').addClass('black-dialog-wrap move-dialog');
|
||||
|
||||
return _getMovableRecords(datas)
|
||||
.then((data) => {
|
||||
if (data.success !== undefined) {
|
||||
if (data.success === true) {
|
||||
$dialog.setContent(data.template);
|
||||
_bindFormEvents();
|
||||
} else {
|
||||
if (data.message !== undefined) {
|
||||
$dialog.setContent(data.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (data) => {
|
||||
if (data.message !== undefined) {
|
||||
$dialog.setContent(data.message);
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
const _bindFormEvents = () => {
|
||||
$dialog = dialog.get(1);
|
||||
|
||||
var $form = $dialog.getDomElement();
|
||||
var buttons = {};
|
||||
|
||||
buttons[localeService.t('valider')] = function () {
|
||||
var coll_son = $('input[name="chg_coll_son"]:checked', $form).length > 0 ? '1' : '0';
|
||||
var datas = {
|
||||
lst: $('input[name="lst"]', $form).val(),
|
||||
base_id: $('select[name="base_id"]', $form).val(),
|
||||
chg_coll_son: coll_son
|
||||
};
|
||||
|
||||
var buttonPanel = $dialog.getDomElement()
|
||||
.closest('.ui-dialog')
|
||||
.find('.ui-dialog-buttonpane');
|
||||
|
||||
|
||||
$(":button:contains('" + localeService.t('valider') + "')", buttonPanel)
|
||||
.attr('disabled', true).addClass('ui-state-disabled');
|
||||
|
||||
_postMovableRecords(datas).then(
|
||||
(data) => {
|
||||
$dialog.close();
|
||||
if (data.success) {
|
||||
humane.info(data.message);
|
||||
} else {
|
||||
humane.error(data.message);
|
||||
}
|
||||
$(":button:contains('" + localeService.t('valider') + "')", buttonPanel)
|
||||
.attr('disabled', false).removeClass('ui-state-disabled');
|
||||
},
|
||||
() => {
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
$dialog.setOption('buttons', buttons);
|
||||
};
|
||||
|
||||
const _getMovableRecords = (datas) => {
|
||||
return $.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/records/movecollection/`,
|
||||
data: datas
|
||||
});
|
||||
};
|
||||
|
||||
const _postMovableRecords = (datas) => {
|
||||
return $.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/records/movecollection/apply/`,
|
||||
dataType: 'json',
|
||||
data: datas
|
||||
});
|
||||
};
|
||||
|
||||
return { openModal };
|
||||
};
|
||||
|
||||
export default moveRecord;
|
77
Phraseanet-production-client/src/components/record/print.js
Normal file
77
Phraseanet-production-client/src/components/record/print.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import $ from 'jquery';
|
||||
const printRecord = (services) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let $container = null;
|
||||
|
||||
appEvents.listenAll({
|
||||
'record.doPrint': doPrint
|
||||
});
|
||||
|
||||
const initialize = () => {
|
||||
$container = $('body');
|
||||
$container.on('click', '.record-print-action', function (event) {
|
||||
event.preventDefault();
|
||||
let $el = $(event.currentTarget);
|
||||
let key = '';
|
||||
let kind = $el.data('kind');
|
||||
let idContent = $el.data('id');
|
||||
|
||||
switch (kind) {
|
||||
case 'basket':
|
||||
key = 'ssel';
|
||||
break;
|
||||
case 'record':
|
||||
key = 'lst';
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
doPrint(`${key}=${idContent}`);
|
||||
});
|
||||
};
|
||||
|
||||
const openModal = (datas) => {
|
||||
return doPrint($.param(datas))
|
||||
}
|
||||
|
||||
function doPrint(value) {
|
||||
if ($('#DIALOG').data('ui-dialog')) {
|
||||
$('#DIALOG').dialog('destroy');
|
||||
}
|
||||
$('#DIALOG').attr('title', localeService.t('print'))
|
||||
.empty().addClass('loading')
|
||||
.dialog({
|
||||
resizable: false,
|
||||
closeOnEscape: true,
|
||||
modal: true,
|
||||
width: '800',
|
||||
height: '500',
|
||||
open: function (event, ui) {
|
||||
$(this).dialog('widget').css('z-index', '1999');
|
||||
},
|
||||
close: function (event, ui) {
|
||||
$(this).dialog('widget').css('z-index', 'auto');
|
||||
}
|
||||
})
|
||||
.dialog('open');
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: `${url}prod/printer/?${value}`,
|
||||
dataType: 'html',
|
||||
beforeSend: function () {
|
||||
|
||||
},
|
||||
success: function (data) {
|
||||
$('#DIALOG').removeClass('loading').empty()
|
||||
.append(data);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {initialize, openModal};
|
||||
};
|
||||
|
||||
export default printRecord;
|
137
Phraseanet-production-client/src/components/record/property.js
Normal file
137
Phraseanet-production-client/src/components/record/property.js
Normal file
@@ -0,0 +1,137 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
|
||||
const propertyRecord = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const openModal = (datas) => {
|
||||
return doProperty(datas);
|
||||
};
|
||||
|
||||
const doProperty = (datas) => {
|
||||
var $dialog = dialog.create(services, {
|
||||
size: 'Medium',
|
||||
title: $('#property-title').val()
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
data: datas,
|
||||
url: `${url}prod/records/property/`,
|
||||
success: function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onPropertyReady($dialog);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const _onPropertyReady = ($dialog) => {
|
||||
$('#tabs-records-property').tabs({
|
||||
beforeLoad: function (event, ui) {
|
||||
|
||||
ui.ajaxSettings.data = {
|
||||
lst: $('input[name=original_selection]', $(this)).val(),
|
||||
};
|
||||
|
||||
// load template only once
|
||||
if (ui.tab.data('loaded')) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
ui.jqXHR.success(function () {
|
||||
ui.tab.data('loaded', true);
|
||||
ui.tab.find('span').html('');
|
||||
typeTabContent($dialog, '#' + ui.tab.attr('aria-controls'));
|
||||
});
|
||||
|
||||
ui.tab.find('span').html('<i>' + localeService.t('loading') + '</i>');
|
||||
},
|
||||
load: function (event, ui) {
|
||||
ui.tab.find('span').empty();
|
||||
}
|
||||
});
|
||||
propertyTabContent($dialog);
|
||||
|
||||
|
||||
};
|
||||
/**
|
||||
* Property Tab
|
||||
* @param $dialogBox
|
||||
*/
|
||||
const propertyTabContent = ($dialog) => {
|
||||
|
||||
const $propertyContainer = $('#property-status');
|
||||
|
||||
$propertyContainer.on('click', 'button.cancel', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
|
||||
$propertyContainer.on('click', 'button.submiter', function () {
|
||||
var $this = $(this);
|
||||
var form = $(this).closest('form');
|
||||
var loader = form.find('form-action-loader');
|
||||
|
||||
$.ajax({
|
||||
type: form.attr('method'),
|
||||
url: form.attr('action'),
|
||||
data: form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
$this.attr('disabled', true);
|
||||
loader.show();
|
||||
},
|
||||
success: function (data) {
|
||||
$dialog.close();
|
||||
},
|
||||
complete: function () {
|
||||
$this.attr('disabled', false);
|
||||
loader.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Type Tab
|
||||
* @param $dialog
|
||||
* @param typeContainerId
|
||||
*/
|
||||
const typeTabContent = ($dialog, typeContainerId) => {
|
||||
|
||||
const $typeContainer = $(typeContainerId);
|
||||
|
||||
$typeContainer.on('click', 'button.cancel', function () {
|
||||
$dialog.close();
|
||||
});
|
||||
$typeContainer.on('click', 'button.submiter', function () {
|
||||
var $this = $(this);
|
||||
var form = $(this).closest('form');
|
||||
var loader = form.find('form-action-loader');
|
||||
|
||||
$.ajax({
|
||||
type: form.attr('method'),
|
||||
url: form.attr('action'),
|
||||
data: form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
$this.attr('disabled', true);
|
||||
loader.show();
|
||||
},
|
||||
success: function (data) {
|
||||
$dialog.close();
|
||||
},
|
||||
complete: function () {
|
||||
$this.attr('disabled', false);
|
||||
loader.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {openModal};
|
||||
};
|
||||
|
||||
export default propertyRecord;
|
@@ -0,0 +1,24 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import publication from '../publication';
|
||||
|
||||
const recordPublishModal = (services, datas) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
const openModal = (datas) => {
|
||||
|
||||
$.post(`${url}prod/feeds/requestavailable/`
|
||||
, datas
|
||||
, function (data) {
|
||||
|
||||
return publication(services).openModal(data);
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return { openModal };
|
||||
};
|
||||
|
||||
export default recordPublishModal;
|
44
Phraseanet-production-client/src/components/record/push.js
Normal file
44
Phraseanet-production-client/src/components/record/push.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../phraseanet-common/components/dialog';
|
||||
import pushRecordWindow from './recordPush/index';
|
||||
|
||||
const pushRecord = (services, datas) => {
|
||||
const {configService, localeService, appEvents} = services;
|
||||
const url = configService.get('baseUrl');
|
||||
|
||||
|
||||
const openModal = (datas) => {
|
||||
|
||||
let $dialog = dialog.create(services, {
|
||||
size: 'Full',
|
||||
title: localeService.t('push')
|
||||
});
|
||||
|
||||
$dialog.getDomElement().closest('.ui-dialog').addClass('push_dialog_container');
|
||||
|
||||
$.post(`${url}prod/push/sendform/`, datas, function (data) {
|
||||
$dialog.setContent(data);
|
||||
_onDialogReady();
|
||||
return;
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const _onDialogReady = () => {
|
||||
pushRecordWindow(services).initialize({
|
||||
feedback: {
|
||||
containerId: '#PushBox',
|
||||
context: 'Push'
|
||||
},
|
||||
listManager: {
|
||||
containerId: '#ListManager'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {openModal};
|
||||
};
|
||||
|
||||
export default pushRecord;
|
@@ -0,0 +1,331 @@
|
||||
import $ from 'jquery';
|
||||
import dialog from './../../../phraseanet-common/components/dialog';
|
||||
|
||||
const recordBridge = (services) => {
|
||||
const { configService, localeService, appEvents } = services;
|
||||
const url = configService.get('baseUrl');
|
||||
let pub_tabs = $('#pub_tabs');
|
||||
let container = $('#dialog_publicator');
|
||||
let managerUrl = container.data('url');
|
||||
let $panel;
|
||||
const initialize = () => {
|
||||
pub_tabs.tabs({
|
||||
beforeLoad: function (event, ui) {
|
||||
ui.tab.html_tab = ui.tab.find('span').html();
|
||||
ui.tab.find('span').html('<i>' + localeService.t('Loading') + '...</i>');
|
||||
},
|
||||
load: function (event, ui) {
|
||||
ui.tab.find('span').empty().append(ui.tab.html_tab);
|
||||
$panel = $(ui.panel);
|
||||
$('.container-bridge', $panel).removeClass('loading');
|
||||
$panel.addClass('PNB');
|
||||
$panel.wrapInner("<div class='PNB10 container-bridge' />");
|
||||
panel_load($panel);
|
||||
},
|
||||
beforeActivate: function (event, ui) {
|
||||
if ($(ui.tab).hasClass('account')) {
|
||||
var container = $('.container-bridge', ui.panel);
|
||||
container.empty();
|
||||
$('.container', ui.panel).addClass('loading');
|
||||
}
|
||||
}
|
||||
}).addClass('ui-tabs-vertical ui-helper-clearfix');
|
||||
|
||||
$('.ui-tabs-nav', pub_tabs).removeClass('ui-corner-all');
|
||||
|
||||
|
||||
$('.new_bridge_button', pub_tabs).bind('click', function () {
|
||||
var url = $(this).parent('form').find('input[name="url"]').val();
|
||||
popme(url);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('ul li a.account', pub_tabs).bind('click', function () {
|
||||
$('#dialog_publicator form[name="current_datas"] input[name="account_id"]').val($('input[name="account_id"]', this).val());
|
||||
});
|
||||
|
||||
$('ul li.ui-tabs-selected a.account', pub_tabs).trigger('click');
|
||||
|
||||
$('#publicator_selection .PNB10:first').selectable();
|
||||
|
||||
$('#publicator_selection button.act_upload').bind('click', function () {
|
||||
|
||||
var $this = $(this);
|
||||
var $form = $this.closest('form');
|
||||
|
||||
$('input[name=lst]', $form).val(
|
||||
$.makeArray(
|
||||
$('#publicator_selection .diapo.ui-selected').map(function (i, el) {
|
||||
return $(el).attr('id').split('_').slice(2, 4).join('_');
|
||||
})
|
||||
).join(';')
|
||||
);
|
||||
|
||||
var account_id = $('form[name="current_datas"] input[name="account_id"]').val();
|
||||
$('input[name="account_id"]', $form).val(account_id);
|
||||
|
||||
var $panel = $('#pub_tabs .ui-tabs-panel:visible');
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: `${url}prod/bridge/upload/`,
|
||||
data: $form.serializeArray(),
|
||||
beforeSend: function () {
|
||||
$panel.empty().addClass('loading');
|
||||
},
|
||||
success: function (datas) {
|
||||
$panel.removeClass('loading').append(datas);
|
||||
panel_load($panel);
|
||||
},
|
||||
error: function () {
|
||||
$panel.removeClass('loading');
|
||||
},
|
||||
timeout: function () {
|
||||
$panel.removeClass('loading');
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('li', pub_tabs).removeClass('ui-corner-top').addClass('ui-corner-left');
|
||||
|
||||
$('#api_connexion').click(function () {
|
||||
if (container.data('ui-dialog')) {
|
||||
container.dialog('close');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function popme(url) {
|
||||
var newwindow = window.open(url, 'logger', 'height=500,width=800');
|
||||
if (window.focus) {
|
||||
newwindow.focus();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function panel_load($panel) {
|
||||
$('.new_bridge_button', $panel).bind('click', function () {
|
||||
var url = $(this).parent('form').find('input[name="url"]').val();
|
||||
popme(url);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.error_box, .notice_box', $panel).delay(10000).fadeOut();
|
||||
|
||||
$('.back_link', $panel).bind('click', function () {
|
||||
if ($('#pub_tabs').data('ui-tabs')) {
|
||||
$('#pub_tabs').tabs('load', $('#pub_tabs').tabs('option', 'active'));
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.bridge_action', $panel).bind('click', function () {
|
||||
var $this = $(this);
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $(this).attr('href'),
|
||||
beforeSend: function () {
|
||||
var container = $('.container-bridge', $panel);
|
||||
container.empty();
|
||||
if (!$this.hasClass('bridge_logout')) {
|
||||
container.addClass('loading');
|
||||
}
|
||||
},
|
||||
success: function (datas) {
|
||||
$('.container-bridge', $panel).removeClass('loading').append(datas);
|
||||
panel_load($panel);
|
||||
},
|
||||
error: function () {
|
||||
$panel.removeClass('loading');
|
||||
},
|
||||
timeout: function () {
|
||||
$panel.removeClass('loading');
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.delete-account', $panel).bind('click', function () {
|
||||
let account_id = $(this).val();
|
||||
let buttons = {};
|
||||
|
||||
buttons[localeService.t('valider')] = function () {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
url: `${url}prod/bridge/adapter/${account_id}/delete/`,
|
||||
data: {},
|
||||
success: function (datas) {
|
||||
if (datas.success) {
|
||||
confirmBox.close();
|
||||
appEvents.emit('push.reload', managerUrl);
|
||||
// pushModule.reloadBridge(managerUrl);
|
||||
} else {
|
||||
confirmBox.close();
|
||||
var alertBox = dialog.create(services, {
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true
|
||||
}, 2);
|
||||
|
||||
alertBox.setContent(datas.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var confirmBox = dialog.create(services, {
|
||||
size: 'Alert',
|
||||
closeOnEscape: true,
|
||||
closeButton: true,
|
||||
cancelButton: true,
|
||||
buttons: buttons
|
||||
}, 2);
|
||||
|
||||
confirmBox.setContent(localeService.t('You are about to delete this account. Would you like to continue ?'));
|
||||
});
|
||||
|
||||
$('.form_submitter', $panel).bind('click', function () {
|
||||
var $form = $(this).closest('form');
|
||||
var method = $form.attr('method');
|
||||
|
||||
method = $.inArray(method.toLowerCase(), ['post', 'get']) ? method : 'POST';
|
||||
|
||||
$.ajax({
|
||||
type: method,
|
||||
url: $form.attr('action'),
|
||||
data: $form.serializeArray(),
|
||||
beforeSend: function () {
|
||||
$panel.empty().addClass('loading');
|
||||
},
|
||||
success: function (datas) {
|
||||
$panel.removeClass('loading').append(datas);
|
||||
panel_load($panel);
|
||||
},
|
||||
error: function () {
|
||||
$panel.removeClass('loading');
|
||||
},
|
||||
timeout: function () {
|
||||
$panel.removeClass('loading');
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('.bridge_all_selector', $panel).bind('click', function () {
|
||||
var checkboxes = $('.bridge_element_selector', $panel);
|
||||
var $this = $(this);
|
||||
|
||||
checkboxes.each(function (i, checkbox) {
|
||||
if ($(checkbox).is(':checked') !== $this.is(':checked')) {
|
||||
var event = $.Event('click');
|
||||
event.selector_all = true;
|
||||
$(checkbox).trigger(event);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.bridge_element_selector', $panel)
|
||||
.bind('click', function (event) {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
if (event.selector_all) {
|
||||
$this.prop('checked', $('.bridge_all_selector', $panel).is(':checked'));
|
||||
}
|
||||
|
||||
$('form[name="bridge_selection"] input[name="elements_list"]', $panel).val(
|
||||
$.makeArray($('.bridge_element_selector:checked', $panel).map(function (i, el) {
|
||||
return ($(el).val());
|
||||
})).join(';')
|
||||
);
|
||||
|
||||
if ($this.is(':checked')) {
|
||||
$this.closest('.element').addClass('selected');
|
||||
} else {
|
||||
$this.closest('.element').removeClass('selected');
|
||||
}
|
||||
|
||||
if (!event.selector_all) {
|
||||
var bool = !($('.bridge_element_selector:checked', $panel).length !== $('.bridge_element_selector', $panel).length);
|
||||
$('.bridge_all_selector', $panel).prop('checked', bool);
|
||||
} else {
|
||||
if (event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('a.form_multiple_submitter', $panel).bind('click', function () {
|
||||
|
||||
var $form = $(this).closest('form');
|
||||
var elements = $('form[name="bridge_selection"] input[name="elements_list"]', $panel).val();
|
||||
|
||||
var n_elements = 0;
|
||||
if ($.trim(elements) !== '') {
|
||||
n_elements = elements.split(';').length;
|
||||
}
|
||||
|
||||
if (n_elements === 0 && $form.hasClass('action_works_standalone') === false) {
|
||||
alert('No records selected');
|
||||
|
||||
return false;
|
||||
}
|
||||
if (n_elements === 1 && $form.hasClass('action_works_single_element') === false) {
|
||||
alert('This action works only with a single records');
|
||||
|
||||
return false;
|
||||
}
|
||||
if (n_elements > 1 && $form.hasClass('action_works_many_element') === false) {
|
||||
alert('This action works only with many records');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$('input[name="elements_list"]', $form).val(elements);
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $form.attr('action'),
|
||||
data: $form.serializeArray(),
|
||||
beforeSend: function () {
|
||||
$panel.empty().addClass('loading');
|
||||
},
|
||||
success: function (datas) {
|
||||
$panel.removeClass('loading').append(datas);
|
||||
panel_load($panel);
|
||||
},
|
||||
error: function () {
|
||||
$panel.removeClass('loading');
|
||||
},
|
||||
timeout: function () {
|
||||
$panel.removeClass('loading');
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
initialize
|
||||
};
|
||||
};
|
||||
export default recordBridge;
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,176 @@
|
||||
import $ from 'jquery';
|
||||
import * as appCommons from './../../../phraseanet-common';
|
||||
|
||||
const recordEditorLayout = services => {
|
||||
const { configService, localeService, recordEditorEvents } = services;
|
||||
let $container = null;
|
||||
let parentOptions = {};
|
||||
|
||||
const initialize = options => {
|
||||
let initWith = ({ $container, parentOptions } = options);
|
||||
$(window).bind('resize', function () {
|
||||
recordEditorEvents.emit('recordEditor.uiResize');
|
||||
_setSizeLimits();
|
||||
});
|
||||
|
||||
_hsplit1();
|
||||
_vsplit2();
|
||||
_vsplit1();
|
||||
|
||||
$('#EDIT_TOP', parentOptions.$container).resizable({
|
||||
handles: 's',
|
||||
minHeight: 100,
|
||||
resize: function () {
|
||||
_hsplit1();
|
||||
recordEditorEvents.emit('recordEditor.uiResize');
|
||||
},
|
||||
stop: function () {
|
||||
_hsplit1();
|
||||
appCommons.userModule.setPref(
|
||||
'editing_top_box',
|
||||
Math.floor(
|
||||
$('#EDIT_TOP').height() * 100 / $('#EDIT_ALL').height()
|
||||
)
|
||||
);
|
||||
_setSizeLimits();
|
||||
}
|
||||
});
|
||||
|
||||
$('#divS_wrapper', parentOptions.$container).resizable({
|
||||
handles: 'e',
|
||||
minWidth: 200,
|
||||
resize: function () {
|
||||
_vsplit1();
|
||||
recordEditorEvents.emit('recordEditor.uiResize');
|
||||
},
|
||||
stop: function () {
|
||||
appCommons.userModule.setPref(
|
||||
'editing_right_box',
|
||||
Math.floor(
|
||||
$('#divS').width() * 100 / $('#EDIT_MID_L').width()
|
||||
)
|
||||
);
|
||||
_vsplit1();
|
||||
_setSizeLimits();
|
||||
}
|
||||
});
|
||||
|
||||
$('#EDIT_MID_R')
|
||||
.css(
|
||||
'left',
|
||||
$('#EDIT_MID_L').position().left + $('#EDIT_MID_L').width() + 15
|
||||
)
|
||||
.resizable({
|
||||
handles: 'w',
|
||||
minWidth: 200,
|
||||
resize: function () {
|
||||
_vsplit2();
|
||||
recordEditorEvents.emit('recordEditor.uiResize');
|
||||
},
|
||||
stop: function () {
|
||||
appCommons.userModule.setPref(
|
||||
'editing_left_box',
|
||||
Math.floor(
|
||||
$('#EDIT_MID_R').width() *
|
||||
100 /
|
||||
$('#EDIT_MID').width()
|
||||
)
|
||||
);
|
||||
_vsplit2();
|
||||
_setSizeLimits();
|
||||
}
|
||||
});
|
||||
|
||||
$('#EDIT_ZOOMSLIDER', parentOptions.$container).slider({
|
||||
min: 60,
|
||||
max: 300,
|
||||
value: parentOptions.recordConfig.diapoSize,
|
||||
slide: function (event, ui) {
|
||||
var v = $(ui.value)[0];
|
||||
$('#EDIT_FILM2 .diapo', parentOptions.$container)
|
||||
.width(v)
|
||||
.height(v);
|
||||
},
|
||||
change: function (event, ui) {
|
||||
parentOptions.recordConfig.diapoSize = $(ui.value)[0];
|
||||
appCommons.userModule.setPref(
|
||||
'editing_images_size',
|
||||
parentOptions.recordConfig.diapoSize
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
_setSizeLimits();
|
||||
};
|
||||
|
||||
function _setSizeLimits() {
|
||||
if (!$('#EDITWINDOW').is(':visible')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($('#EDIT_TOP').data('ui-resizable')) {
|
||||
$('#EDIT_TOP').resizable(
|
||||
'option',
|
||||
'maxHeight',
|
||||
$('#EDIT_ALL').height() -
|
||||
$('#buttonEditing').height() -
|
||||
10 -
|
||||
160
|
||||
);
|
||||
}
|
||||
if ($('#divS_wrapper').data('ui-resizable')) {
|
||||
$('#divS_wrapper').resizable(
|
||||
'option',
|
||||
'maxWidth',
|
||||
$('#EDIT_MID_L').width() - 270
|
||||
);
|
||||
}
|
||||
if ($('#EDIT_MID_R').data('ui-resizable')) {
|
||||
$('#EDIT_MID_R').resizable(
|
||||
'option',
|
||||
'maxWidth',
|
||||
$('#EDIT_MID_R').width() + $('#idEditZone').width() - 240
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function _hsplit1() {
|
||||
let el = $('#EDIT_TOP');
|
||||
if (el.length === 0) {
|
||||
return;
|
||||
}
|
||||
let h = $(el).outerHeight();
|
||||
$(el).height(h);
|
||||
let t = $(el).offset().top + h;
|
||||
|
||||
$('#EDIT_MID', parentOptions.$container).css('top', t + 'px');
|
||||
}
|
||||
|
||||
function _vsplit1() {
|
||||
$('#divS_wrapper').height('auto');
|
||||
|
||||
let el = $('#divS_wrapper');
|
||||
if (el.length === 0) {
|
||||
return;
|
||||
}
|
||||
let a = $(el).width();
|
||||
el.width(a);
|
||||
|
||||
$('#idEditZone', parentOptions.$container).css('left', a + 20);
|
||||
}
|
||||
|
||||
function _vsplit2() {
|
||||
let el = $('#EDIT_MID_R');
|
||||
if (el.length === 0) {
|
||||
return;
|
||||
}
|
||||
let a = $(el).width();
|
||||
el.width(a);
|
||||
let v = $('#EDIT_ALL').width() - a - 35;
|
||||
|
||||
$('#EDIT_MID_L', parentOptions.$container).width(v);
|
||||
}
|
||||
|
||||
return { initialize };
|
||||
};
|
||||
export default recordEditorLayout;
|
@@ -0,0 +1,81 @@
|
||||
import merge from 'lodash.merge';
|
||||
|
||||
class FieldCollection {
|
||||
fields;
|
||||
|
||||
constructor(fieldsList) {
|
||||
this.fields = fieldsList;
|
||||
}
|
||||
|
||||
getFields() {
|
||||
return this.fields;
|
||||
}
|
||||
|
||||
getFieldOptionsById(meta_struct_id) {
|
||||
/*var name = this.fields[meta_struct_id].name;
|
||||
var label = this.fields[meta_struct_id].label;
|
||||
var multi = ;
|
||||
var required = this.fields[meta_struct_id].required;
|
||||
var readonly = this.fields[meta_struct_id].readonly;
|
||||
var maxLength = this.fields[meta_struct_id].maxLength;
|
||||
var minLength = this.fields[meta_struct_id].minLength;
|
||||
var type = this.fields[meta_struct_id].type;
|
||||
var separator = this.fields[meta_struct_id].separator;
|
||||
var vocabularyControl = this.fields[meta_struct_id].vocabularyControl || null;
|
||||
var vocabularyRestricted = this.fields[meta_struct_id].vocabularyRestricted || null;*/
|
||||
|
||||
return {
|
||||
multi: this.fields[meta_struct_id].multi,
|
||||
required: this.fields[meta_struct_id].required,
|
||||
readonly: this.fields[meta_struct_id].readonly,
|
||||
maxLength: this.fields[meta_struct_id].maxLength,
|
||||
minLength: this.fields[meta_struct_id].minLength,
|
||||
type: this.fields[meta_struct_id].type,
|
||||
separator: this.fields[meta_struct_id].separator,
|
||||
vocabularyControl: this.fields[meta_struct_id].vocabularyControl || null,
|
||||
vocabularyRestricted: this.fields[meta_struct_id].vocabularyRestricted || null
|
||||
};
|
||||
}
|
||||
|
||||
setActiveField(metaStructId) {
|
||||
this.metaStructId = metaStructId;
|
||||
}
|
||||
|
||||
getActiveFieldIndex() {
|
||||
return this.metaStructId === undefined ? '?' : this.metaStructId;
|
||||
}
|
||||
|
||||
getActiveField() {
|
||||
return this.fields[this.getActiveFieldIndex()]
|
||||
}
|
||||
|
||||
getFieldByIndex(id = false) {
|
||||
if (this.fields[id] !== undefined) {
|
||||
return this.fields[id];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getFieldByName(fieldName) {
|
||||
let foundField = false;
|
||||
for (let field in this.fields) {
|
||||
if (this.fields[field].name === fieldName) {
|
||||
foundField = this.fields[field];
|
||||
}
|
||||
}
|
||||
return foundField;
|
||||
}
|
||||
|
||||
getFieldStatus(id = false) {
|
||||
|
||||
}
|
||||
|
||||
updateField(id, data) {
|
||||
if (this.fields[id] !== undefined) {
|
||||
this.fields[id] = merge(this.fields[id], data);
|
||||
return this.fields[id];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
export default FieldCollection;
|
@@ -0,0 +1,193 @@
|
||||
import FieldCollection from './fieldCollection';
|
||||
import * as recordModel from '../../../record/model';
|
||||
class RecordCollection {
|
||||
records;
|
||||
fieldCollection;
|
||||
statbitCollection;
|
||||
constructor(recordsList, fieldsColl, statusbitList, predefinedValues) {
|
||||
this.records = recordsList;
|
||||
this.statusbits = statusbitList;
|
||||
this.fieldCollection = fieldsColl;
|
||||
this.predefinedValues = predefinedValues;
|
||||
// set each models
|
||||
this.initializeRecordModels();
|
||||
}
|
||||
getRecords() {
|
||||
return this.records;
|
||||
}
|
||||
getRecordByIndex(id = false) {
|
||||
if (this.records[id] !== undefined) {
|
||||
return this.records[id];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
initializeRecordModels() {
|
||||
for (let recordIndex in this.records) {
|
||||
// let fields = this.setRecordFields(recordIndex);
|
||||
this.records[recordIndex].fields = this.setRecordFields(recordIndex);
|
||||
//options.fields = fields;
|
||||
|
||||
}
|
||||
}
|
||||
setRecordFields(recordIndex) {
|
||||
let fields = {};
|
||||
for (let fieldIndex in this.records[recordIndex].fields) {
|
||||
var meta_struct_id = this.records[recordIndex].fields[fieldIndex].meta_struct_id;
|
||||
|
||||
|
||||
let currentField = this.fieldCollection.getFieldByIndex(meta_struct_id);
|
||||
var fieldOptions = this.fieldCollection.getFieldOptionsById(meta_struct_id);
|
||||
|
||||
var databoxField = new recordModel.databoxField(currentField.name, currentField.label, meta_struct_id, fieldOptions);
|
||||
|
||||
var values = [];
|
||||
|
||||
for (let v in this.records[recordIndex].fields[fieldIndex].values) {
|
||||
var meta_id = this.records[recordIndex].fields[fieldIndex].values[v].meta_id;
|
||||
var value = this.records[recordIndex].fields[fieldIndex].values[v].value;
|
||||
var vocabularyId = this.records[recordIndex].fields[fieldIndex].values[v].vocabularyId;
|
||||
|
||||
values.push(new recordModel.recordFieldValue(meta_id, value, vocabularyId));
|
||||
}
|
||||
|
||||
fields[fieldIndex] = new recordModel.recordField(databoxField, values);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge all suggestions for 1 or n records
|
||||
* @returns {{}}
|
||||
*/
|
||||
getFieldSuggestedValues() {
|
||||
var suggestedValuesCollection = {};
|
||||
var t_selcol = {};
|
||||
var ncolsel = 0;
|
||||
var nrecsel = 0;
|
||||
for (let recordIndex in this.records) {
|
||||
if (!this.records[recordIndex]._selected) {
|
||||
continue;
|
||||
}
|
||||
nrecsel++;
|
||||
|
||||
var bid = 'b' + this.records[recordIndex].bid;
|
||||
if (t_selcol[bid]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
t_selcol[bid] = 1;
|
||||
ncolsel++;
|
||||
for (let f in this.predefinedValues[bid]) {
|
||||
if (!suggestedValuesCollection[f]) {
|
||||
suggestedValuesCollection[f] = {};
|
||||
}
|
||||
for (let ivs in this.predefinedValues[bid][f]) {
|
||||
let vs = this.predefinedValues[bid][f][ivs];
|
||||
if (!suggestedValuesCollection[f][vs]) {
|
||||
suggestedValuesCollection[f][vs] = 0;
|
||||
}
|
||||
suggestedValuesCollection[f][vs]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return suggestedValuesCollection;
|
||||
}
|
||||
|
||||
setStatus(bit, val) {
|
||||
for (let id in this.records) {
|
||||
// toutes les fiches selectionnees
|
||||
if (this.records[id]._selected) {
|
||||
if (this.records[id].editableStatus === true) {
|
||||
this.records[id].statbits[bit].value = val;
|
||||
this.records[id].statbits[bit].dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isDirty() {
|
||||
let dirty = false;
|
||||
for (let recordIndex in this.records) {
|
||||
for (let fieldIndex in this.records[recordIndex].fields) {
|
||||
if ((dirty |= this.records[recordIndex].fields[fieldIndex].isDirty())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let bitIndex in this.records[recordIndex].statbits) {
|
||||
if ((dirty |= this.records[recordIndex].statbits[bitIndex].dirty)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
|
||||
gatherUpdatedRecords() {
|
||||
let t = [];
|
||||
|
||||
for (let recordIndex in this.records) {
|
||||
let record_datas = {
|
||||
record_id: this.records[recordIndex].rid,
|
||||
metadatas: [],
|
||||
edit: 0,
|
||||
status: null
|
||||
};
|
||||
|
||||
let editDirty = false;
|
||||
|
||||
for (let f in this.records[recordIndex].fields) {
|
||||
if (!this.records[recordIndex].fields[f].isDirty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
editDirty = true;
|
||||
record_datas.edit = 1;
|
||||
|
||||
record_datas.metadatas = record_datas.metadatas.concat(
|
||||
this.records[recordIndex].fields[f].exportDatas()
|
||||
);
|
||||
}
|
||||
|
||||
// les statbits
|
||||
let tsb = [];
|
||||
for (let n = 0; n < 64; n++) {
|
||||
tsb[n] = 'x';
|
||||
}
|
||||
let sb_dirty = false;
|
||||
for (let n in this.records[recordIndex].statbits) {
|
||||
if (this.records[recordIndex].statbits[n].dirty) {
|
||||
tsb[63 - n] = this.records[recordIndex].statbits[n].value;
|
||||
sb_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sb_dirty || editDirty) {
|
||||
if (sb_dirty === true) {
|
||||
record_datas.status = tsb.join('');
|
||||
}
|
||||
|
||||
t.push(record_datas);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
removeRecordFieldValue(recordIndex, fieldIndex, params) {
|
||||
let {value, vocabularyId} = params;
|
||||
this.records[recordIndex].fields[fieldIndex].removeValue(value, vocabularyId);
|
||||
}
|
||||
|
||||
addRecordFieldValue(recordIndex, fieldIndex, params) {
|
||||
let {value, merge, vocabularyId} = params;
|
||||
this.records[recordIndex].fields[fieldIndex].addValue(value, merge, vocabularyId);
|
||||
}
|
||||
|
||||
/* options.recordCollection.removeRecordFieldValue(r, currentFieldId, {
|
||||
value, vocabularyId
|
||||
})*/
|
||||
// currentRecord.fields[currentFieldId].removeValue(value, VocabularyId);
|
||||
|
||||
|
||||
}
|
||||
export default RecordCollection;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user