From 1e950797c102989188bde4f2e2ee42359ec7505e Mon Sep 17 00:00:00 2001 From: Benjamin Gerber Date: Fri, 30 Aug 2024 09:05:42 +0200 Subject: [PATCH 1/2] Remove style ordering by webpack plugin --- .gitignore | 1 + .npmignore | 1 + buildtools/webpack.commons.js | 104 +--- buildtools/webpack.plugin.js | 554 ------------------ buildtools/webpack.scss-loader.js | 82 --- contribs/gmf/apps/desktop/Controller.js | 2 +- contribs/gmf/apps/desktop/sass/desktop.scss | 3 + contribs/gmf/apps/desktop_alt/Controller.js | 2 +- .../apps/desktop_alt/sass/desktop_alt.scss | 6 +- contribs/gmf/apps/iframe_api/Controller.js | 3 +- .../gmf/apps/iframe_api/sass/iframe_api.scss | 3 +- contribs/gmf/apps/mobile/Controller.js | 1 - contribs/gmf/apps/mobile/sass/mobile.scss | 3 + contribs/gmf/apps/mobile_alt/Controller.js | 1 - .../gmf/apps/mobile_alt/sass/mobile_alt.scss | 3 + contribs/gmf/apps/oeedit/Controller.js | 1 - contribs/gmf/apps/oeedit/sass/oeedit.scss | 3 + .../gmf/examples/backgroundlayerselector.js | 4 +- contribs/gmf/examples/common_dependencies.js | 4 - contribs/gmf/examples/common_styles.scss | 8 + contribs/gmf/examples/contextualdata.js | 5 +- contribs/gmf/examples/datepicker.js | 4 +- contribs/gmf/examples/displayquerygrid.js | 4 +- contribs/gmf/examples/displayquerywindow.js | 4 +- contribs/gmf/examples/drawfeature.js | 4 +- contribs/gmf/examples/elevation.js | 4 +- contribs/gmf/examples/featurestyle.js | 4 +- contribs/gmf/examples/importdatasource.js | 6 +- contribs/gmf/examples/layertree.js | 6 +- contribs/gmf/examples/layertreeadd.js | 6 +- contribs/gmf/examples/mobilemeasure.js | 4 +- contribs/gmf/examples/mouseposition.js | 2 + contribs/gmf/examples/objectediting.js | 4 +- contribs/gmf/examples/objecteditinghub.js | 4 +- contribs/gmf/examples/options.js | 2 - contribs/gmf/examples/permalink.js | 2 + contribs/gmf/examples/print.js | 4 +- contribs/gmf/examples/profile.js | 5 +- contribs/gmf/examples/search.js | 5 +- contribs/gmf/examples/share.js | 4 +- contribs/gmf/examples/simple.js | 2 + contribs/gmf/examples/themeselector.js | 4 +- contribs/gmf/examples/timeslider.js | 3 + contribs/gmf/examples/wfspermalink.js | 4 +- contribs/gmf/examples/xsdattributes.js | 5 +- docs/guidelines.md | 9 +- examples/animation.js | 2 + examples/asitvd.js | 2 + examples/attributes.js | 2 + examples/backgroundlayer.js | 2 + examples/backgroundlayerdropdown.js | 2 + examples/colorpicker.js | 2 + examples/common_dependencies.js | 6 - examples/common_styles.scss | 7 + examples/control.js | 2 + examples/createfeature.js | 2 + examples/datepicker.js | 2 + examples/datetimepicker.js | 3 + examples/disclaimer.js | 2 + examples/displaywindow.js | 2 + examples/drawfeature.js | 2 + examples/elevationProfile.js | 2 + examples/error.js | 2 + examples/googlestreetview.js | 2 + examples/grid.js | 2 + examples/importfeatures.js | 2 + examples/interactionbtngroup.js | 2 + examples/layerorder.js | 2 + examples/locationsearch.js | 3 + examples/mapfishprint.js | 2 + examples/mapillarystreetview.js | 3 + examples/mapswipe.js | 2 + examples/mask.js | 2 + examples/measure.js | 2 + examples/mobilegeolocation.js | 2 + examples/modal.js | 2 + examples/modifycircle.js | 2 + examples/modifyrectangle.js | 2 + examples/notification.js | 2 + examples/options.js | 2 - examples/permalink.js | 2 + examples/popover.js | 2 + examples/popupservice.js | 2 + examples/query.js | 2 + examples/recenter.js | 2 + examples/rotate.js | 2 + examples/routing.js | 6 +- examples/scaleselector.js | 2 + examples/search.js | 5 +- examples/simple.js | 2 + examples/toolActivate.js | 2 + src/contextualdata/module.js | 2 - src/controllers/AbstractDesktopController.js | 2 - src/controllers/AbstractMobileController.js | 2 - src/controllers/desktop.scss | 36 +- src/controllers/iframe_api.scss | 2 +- src/controllers/mobile-nav.scss | 2 + src/controllers/mobile.scss | 30 +- src/controllers/vars_desktop.scss | 9 +- src/controllers/vars_mobile.scss | 3 +- src/dropfile/dropfile.scss | 2 + src/dropfile/module.js | 1 - src/editing/attributesComponent.js | 1 - src/editing/editFeatureComponent.js | 1 - src/filter/component.js | 1 - src/filter/ruleComponent.js | 2 +- src/floor/floor.scss | 2 + src/floor/module.js | 2 - src/grid/component.js | 2 +- src/import/module.js | 2 - src/layertree/common.scss | 3 + src/layertree/module.js | 5 +- src/layertree/timeSliderComponent.js | 2 - src/layertree/timeslider.scss | 4 +- src/message/Disclaimer.js | 1 - src/message/displaywindowComponent.js | 2 - src/message/modalComponent.js | 1 - src/misc/datepickerComponent.js | 1 - src/misc/datetimepickerComponent.js | 1 - src/misc/sortableComponent.js | 1 - src/permalink/module.js | 2 - src/permalink/share.scss | 2 + src/print/module.js | 2 - src/profile/module.js | 2 - src/profile/profile.scss | 2 + src/query/extraModule.js | 3 - src/query/window.scss | 10 +- src/query/windowComponent.js | 1 - src/routing/RoutingComponent.js | 1 - src/routing/RoutingFeatureComponent.js | 1 - src/routing/module.js | 2 - src/sass/base.scss | 6 +- src/sass/components.scss | 16 + src/sass/font.scss | 24 +- src/sass/fullscreenpopup.scss | 2 +- src/sass/gmf-font.scss | 4 +- src/sass/map.scss | 6 +- src/sass/popover.scss | 8 +- src/sass/typeahead.scss | 2 +- src/sass/vars.scss | 2 +- src/sass/vars_only.scss | 4 +- src/search/module.js | 2 - src/search/search.scss | 8 +- src/spinner/module.js | 2 - src/streetview/MapillaryService.js | 1 - 145 files changed, 327 insertions(+), 921 deletions(-) delete mode 100644 buildtools/webpack.plugin.js delete mode 100644 buildtools/webpack.scss-loader.js rename examples/common_dependencies.scss => contribs/gmf/apps/iframe_api/sass/iframe_api.scss (92%) create mode 100644 contribs/gmf/examples/common_styles.scss create mode 100644 examples/common_styles.scss create mode 100644 src/sass/components.scss diff --git a/.gitignore b/.gitignore index 36b6663db329..086e04ad9eaf 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ /cypress/screenshots/ /cypress/video /locales +/.idea diff --git a/.npmignore b/.npmignore index 5be2d8c2ddea..310d24acbc9a 100644 --- a/.npmignore +++ b/.npmignore @@ -16,6 +16,7 @@ /.storybook/ /.tx/ /.vscode/ +/.idea/ /private.crt /private.key /pyproject.toml diff --git a/buildtools/webpack.commons.js b/buildtools/webpack.commons.js index 9e6c2814333b..d46f9ece14d6 100644 --- a/buildtools/webpack.commons.js +++ b/buildtools/webpack.commons.js @@ -21,8 +21,6 @@ const path = require('path'); const webpack = require('webpack'); -const SassPlugin = require('./webpack.plugin.js'); -const EventHooksPlugin = require('event-hooks-webpack-plugin'); const {PromiseTask} = require('event-hooks-webpack-plugin/lib/tasks'); const devMode = process.env.NODE_ENV !== 'production'; @@ -94,16 +92,12 @@ module.exports = function (config) { const cssRule = { test: /\.css$/, - use: ['./buildtools/webpack.scss-loader', 'extract-loader', 'css-loader'], + use: [{loader: 'style-loader'}, {loader: 'css-loader'}], }; const sassRule = { - test: /\.scss$/, - use: [ - { - loader: './buildtools/webpack.scss-loader', - }, - ], + test: /\.s[ac]ss$/i, + use: [{loader: 'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}], }; const htmlRule = { @@ -116,32 +110,6 @@ module.exports = function (config) { }, }; - /** - * @param firsts - * @param lasts - */ - function get_comp(firsts, lasts) { - return (f1, f2) => { - for (const pattern of firsts) { - if (f1.indexOf(pattern) >= 0) { - return -1; - } - if (f2.indexOf(pattern) >= 0) { - return 1; - } - } - for (const pattern of lasts) { - if (f1.indexOf(pattern) >= 0) { - return 1; - } - if (f2.indexOf(pattern) >= 0) { - return -1; - } - } - return 0; - }; - } - // Collect every ts(x) files. const tsRule = { test: /\.tsx?$/, @@ -210,76 +178,12 @@ module.exports = function (config) { const plugins = [ providePlugin, - new SassPlugin({ - filename: devMode ? '[name].css' : '[name].[hash:6].css', - assetname: '[name].[hash:6].[ext]', - // tempfile: '/tmp/t.scss', - blacklistedChunks: ['commons'], - filesOrder: (chunk, chunksFiles) => { - let files = chunksFiles.commons - ? chunksFiles[chunk.name].concat(chunksFiles.commons) - : chunksFiles[chunk.name]; - files = files.filter((file) => { - if (file.endsWith('node_modules/@fortawesome/fontawesome-free/css/all.min.css')) { - return false; - } - if (file.endsWith('/src/css/reset.css')) { - return false; - } - return true; - }); - files.sort( - get_comp( - config.first_scss || - config.fist_scss || [ - // ngeo default apps - '/apps/desktop/sass/vars_desktop.scss', - '/apps/desktop_alt/sass/vars_desktop_alt.scss', - '/apps/iframe_api/sass/vars_iframe_api.scss', - '/apps/mobile/sass/vars_mobile.scss', - '/apps/mobile_alt/sass/vars_mobile_alt.scss', - '/apps/oeedit/sass/vars_oeedit.scss', - // GeoMapFish project sass vars files - '/apps/sass/vars_', - '/controllers/vars_', - // For the examples - 'examples/vars.scss', - // For the tests - 'sass/vars.scss', - ], - config.last_scss || [ - // project and ngeo default apps other sass files - '/apps/', - '/controllers/', - ], - ), - ); - console.log(); - console.log('SCSS files order:'); - for (const file of files) { - console.log(file); - } - console.log(); - return files; - }, - }), new webpack.IgnorePlugin(/^\.\/locale$/, /node_modules\/moment\/src\/lib\/locale$/), ]; if (config.nodll != true) { plugins.push(dllPlugin); } - plugins.push( - new EventHooksPlugin({ - afterCompile: new PromiseTask(async () => { - console.log('Babel compilations rules'); - for (const file in files) { - console.log(file + ': ' + JSON.stringify(files[file])); - } - }), - }), - ); - plugins.push( new webpack.IgnorePlugin({ resourceRegExp: /^cross-fetch$/, @@ -322,7 +226,7 @@ module.exports = function (config) { olcs: 'ol-cesium/src/olcs', 'jquery-ui/datepicker': 'jquery-ui/ui/widgets/datepicker', // For angular-ui-date 'mapillary-js/src/Mapillary': 'mapillary-js/dist/mapillary.js', - // required to bake it working with types + // required to make it working with types 'typeahead': 'corejs-typeahead', }, }, diff --git a/buildtools/webpack.plugin.js b/buildtools/webpack.plugin.js deleted file mode 100644 index cd0fe7427d6a..000000000000 --- a/buildtools/webpack.plugin.js +++ /dev/null @@ -1,554 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2018-2024 Camptocamp SA -// -// 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. - -'use strict'; - -const sassLoader = require('./webpack.scss-loader.js'); -const nodeSass = require('node-sass'); -const path = require('path'); -const fs = require('fs-extra'); -const co = require('co'); -const replaceAsync = require('fast-sass-loader/lib/replace'); -const utils = require('fast-sass-loader/lib/utils'); -const loaderUtils = require('loader-utils'); -const assert = require('assert'); - -const BOM_HEADER = '\uFEFF'; -const EXT_PRECEDENCE = ['.scss', '.sass', '.css']; -const MATCH_URL_ALL = /url\(\s*(['"]?)([^ '"()]+)(\1)\s*\)/g; -const MATCH_IMPORTS = /@import\s+(['"])([^,;'"]+)(\1)(\s*,\s*(['"])([^,;'"]+)(\1))*\s*;/g; -const MATCH_FILES = /(['"])([^,;'"]+)(\1)/g; - -/** - * @param original - * @param includePaths - * @param transformers - */ -function getImportsToResolve(original, includePaths, transformers) { - const extname = path.extname(original); - let basename = path.basename(original, extname); - const dirname = path.dirname(original); - - const imports = []; - let names = [basename]; - let exts = [extname]; - const extensionPrecedence = [].concat(EXT_PRECEDENCE, Object.keys(transformers)); - - if (!extname) { - exts = extensionPrecedence; - } - if (extname && !extensionPrecedence.includes(extname)) { - basename = path.basename(original); - names = [basename]; - exts = extensionPrecedence; - } - if (!basename.startsWith('_')) { - names.push(`_${basename}`); - } - - // eslint-disable-next-line @typescript-eslint/prefer-for-of - for (let i = 0; i < names.length; i++) { - // eslint-disable-next-line @typescript-eslint/prefer-for-of - for (let j = 0; j < exts.length; j++) { - // search relative to original file - imports.push(path.join(dirname, names[i] + exts[j])); - - // search in includePaths - for (const includePath of includePaths) { - imports.push(path.join(includePath, dirname, names[i] + exts[j])); - } - } - } - - return imports; -} - -let cache; - -/** - * @param opts - * @param entry - * @param resolve - * @param level - */ -function* mergeSources(opts, entry, resolve, level) { - level = level || 0; - - const includePaths = opts.includePaths; - const transformers = opts.transformers; - let content = false; - - if (typeof entry === 'object') { - content = entry.content; - entry = entry.file; - } else { - content = yield fs.readFile(entry, 'utf8'); - - // fix BOM issue (only on windows) - if (content.startsWith(BOM_HEADER)) { - content = content.substring(BOM_HEADER.length); - } - } - - const ext = path.extname(entry); - - if (transformers[ext]) { - content = transformers[ext](content); - } - - if (opts.data) { - content = `${opts.data}\n${content}`; - } - - const entryDir = path.dirname(entry); - - // replace url(...) - content = content.replace(MATCH_URL_ALL, (total, left, file, right) => { - if (loaderUtils.isUrlRequest(file)) { - // handle url(!) - const pos = file.lastIndexOf('!'); - if (pos >= 0) { - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - left += file.substring(0, pos + 1); - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - file = file.substring(pos + 1); - } - - // test again - if (loaderUtils.isUrlRequest(file)) { - if (file.startsWith('~') || file.startsWith('data:')) { - return total; - } - const absoluteFile = path.normalize(path.resolve(entryDir, file)); - // fix for windows path - let relativeFile = path.relative(process.cwd(), absoluteFile).replace(/\\/g, '/'); - - if (!relativeFile.startsWith('.')) { - relativeFile = `./${relativeFile}`; - } - - return `url(${left}${relativeFile}${right})`; - } else { - return total; - } - } else { - return total; - } - }); - - // find comments should after content.replace(...), otherwise the comments offset will be incorrect - const commentRanges = utils.findComments(content); - - // replace @import "..." - /** - * @param total - */ - function* importReplacer(total) { - // if current import is in comments, then skip it - // eslint-disable-next-line @typescript-eslint/no-this-alias - const range = this; - const found = commentRanges.find((commentRange) => { - if (range.start >= commentRange[0] && range.end <= commentRange[1]) { - return true; - } - }); - - if (found) { - return total; - } - - const contents = []; - let matched; - - // must reset lastIndex - MATCH_FILES.lastIndex = 0; - - while ((matched = MATCH_FILES.exec(total))) { - // eslint-disable-line - const originalImport = matched[2].trim(); - if (!originalImport) { - const err = new Error(`import file cannot be empty: "${total}" @${entry}`); - - err.file = entry; - - throw err; - } - - const imports = getImportsToResolve(originalImport, includePaths, transformers); - let resolvedImport; - - // eslint-disable-next-line @typescript-eslint/prefer-for-of - for (let i = 0; i < imports.length; i++) { - // if imports[i] is absolute path, then use it directly - if (path.isAbsolute(imports[i]) && fs.existsSync(imports[i])) { - resolvedImport = imports[i]; - } else { - try { - const reqFile = loaderUtils.urlToRequest(imports[i], opts.root); - - resolvedImport = yield resolve(entryDir, reqFile); - break; - } catch (err) { - // skip - } - } - } - - if (!resolvedImport) { - const err = new Error(`import file cannot be resolved: "${total}" @${entry}`); - - err.file = entry; - - throw err; - } - - resolvedImport = path.normalize(resolvedImport); - - if (cache.indexOf(resolvedImport) < 0) { - cache.push(resolvedImport); - - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - contents.push(yield mergeSources(opts, resolvedImport, resolve, level + 1)); - } - } - - return contents.join('\n'); - } - - return yield replaceAsync(content, MATCH_IMPORTS, co.wrap(importReplacer)); -} - -/** - * @param ctx - */ -function resolver(ctx) { - return function (dir, importFile) { - return new Promise((resolve, reject) => { - ctx.resolve(dir, importFile, (err, resolvedFile) => { - if (err) { - reject(err); - } else { - resolve(resolvedFile); - } - }); - }); - }; -} - -/** - * @param pluginOptions - * @param usedContext - * @param compilation - * @param assetName - * @param assetUrl - * @param queryString - * @param replacements - */ -function fillDependency( - pluginOptions, - usedContext, - compilation, - assetName, - assetUrl, - queryString, - replacements, -) { - return (resolve, reject) => { - if (assetUrl.startsWith('~')) { - usedContext.resolve(usedContext.resourcePath, assetName, (err, resolvedFile) => { - if (err) { - console.log(err); - reject(err); - } else { - fs.readFile(resolvedFile, (err, data) => { - if (err) { - console.log(err); - reject(err); - } else { - usedContext.resourcePath = assetName; - const name = loaderUtils.interpolateName(usedContext, pluginOptions.assetname, { - content: data, - }); - compilation.assets[name] = { - source: () => data, - size: () => data.length, - }; - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - replacements[assetUrl] = name + queryString; - resolve(); - } - }); - } - }); - } else { - fs.readFile(assetName, (err, data) => { - if (err) { - console.log(err); - reject(err); - } else { - usedContext.resourcePath = assetName; - const name = loaderUtils.interpolateName(usedContext, pluginOptions.assetname, { - content: data, - }); - compilation.assets[name] = { - source: () => data, - size: () => data.length, - }; - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - replacements[assetUrl] = name + queryString; - resolve(); - } - }); - } - }; -} - -/** - * @param text - * @param replacements - */ -function doReplacement(text, replacements) { - if (replacements) { - for (const replacement of replacements) { - text = text.replace(replacement[0], replacement[1]); - } - } - return text; -} - -/** - * @param pluginOptions - * @param usedContext - * @param compilation - * @param chunk - * @param resolve - * @param callback - */ -function manageContent(pluginOptions, usedContext, compilation, chunk, resolve, callback) { - return async (contents) => { - if (pluginOptions.tempfile) { - fs.writeFile(pluginOptions.tempfile, contents); - } - - try { - const replacements = {}; - const promises = []; - const options = Object.assign({}, pluginOptions.sassConfig, { - data: doReplacement(contents, pluginOptions.preReplacements), - functions: {}, - }); - // Double parse the Sass files to be able to return in a synchronous function things - // that we can only get asynchronously. - const preparseOptions = Object.assign({}, options); - preparseOptions.functions['url($url)'] = function (url) { - if (url.getValue().startsWith('data:')) { - return url; - } - try { - const assetUrl = url.getValue(); - if (assetUrl[0] == '~') { - let assetName = assetUrl.substr(1); - let queryString = ''; - const questionMarkIndex = assetName.indexOf('?'); - if (questionMarkIndex > 0) { - queryString = assetName.substr(questionMarkIndex); - assetName = assetName.substr(0, questionMarkIndex); - } else { - const sharpIndex = assetName.indexOf('#'); - if (sharpIndex > 0) { - queryString = assetName.substr(sharpIndex); - assetName = assetName.substr(0, sharpIndex); - } - } - promises.push( - new Promise( - fillDependency( - pluginOptions, - usedContext, - compilation, - assetName, - assetUrl, - queryString, - replacements, - ), - ), - ); - } else { - promises.push( - new Promise( - fillDependency(pluginOptions, usedContext, compilation, assetUrl, assetUrl, '', replacements), - ), - ); - } - } catch (e) { - console.error(e.stack || e); - callback(`SCSS plugin error, ${e}`); - } - return url; - }; - const originalResourcePath = usedContext.resourcePath; - nodeSass.renderSync(preparseOptions); - await Promise.all(promises); - const parseOptions = Object.assign({}, options); - parseOptions.functions['url($url)'] = function (url) { - const assetUrl = url.getValue(); - if (assetUrl.startsWith('data:')) { - return nodeSass.types.String(`url(${assetUrl})`); - } - return nodeSass.types.String(`url(${replacements[assetUrl]})`); - }; - const result = nodeSass.renderSync(parseOptions); - const content = doReplacement(result.css.toString(), pluginOptions.postReplacements); - const srcmap = result.map; - const asset = { - source: () => content, - size: () => content.length, - }; - usedContext.resourcePath = `/${chunk.name}`; - const assetName = loaderUtils.interpolateName(usedContext, pluginOptions.filename, { - content: content, - }); - compilation.assets[assetName] = asset; - chunk.files.push(assetName); - if (srcmap) { - compilation.assets[`${assetName}.map`] = { - source: () => srcmap, - size: () => srcmap.length, - }; - chunk.files.push(`${assetName}.map`); - } - usedContext.resourcePath = originalResourcePath; - resolve(); - } catch (e) { - console.error(e.stack || e); - callback(`SCSS plugin error, ${e}`); - } - }; -} - -/** - * @param files - */ -function processAsset(files) { - return (resolve, reject) => { - try { - const contents = []; - const browse = function (position) { - if (position < files.length) { - const file = files[position]; - const entry = sassLoader.entries[file]; - if (entry) { - const merged = mergeSources( - entry.options, - { - file: file, - content: entry.content, - }, - resolver(entry.ctx), - ); - const merged2 = []; - for (const content of merged) { - merged2.push(content); - } - assert.strictEqual(merged2.length, 1); - merged2[0].then( - (content) => { - contents.push(content); - position++; - browse(position); - }, - () => { - reject(`${position}, ${file}`); - }, - ); - } else { - reject(`Missing entry for ${file}`); - } - } else { - resolve(contents.join('\n')); - } - }; - browse(0); - } catch (e) { - console.error(e.stack || e); - reject(e); - } - }; -} - -class SassPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - // compiler.hooks.emit.taplAsync('SassPlugin', async (compilation, callback) => { - compiler.plugin('emit', async (compilation, callback) => { - const chunksFiles = {}; - for (const chunk of compilation.chunks) { - chunksFiles[chunk.name] = []; - const files = chunksFiles[chunk.name]; - const browse = (module) => { - if (module.children) { - for (const child of module.children) { - browse(child); - } - } else { - if (module.resource && (module.resource.endsWith('.scss') || module.resource.endsWith('.css'))) { - files.push(module.resource); - } - } - }; - for (const module of chunk.modulesIterable) { - browse(module); - } - } - for (const chunk of compilation.chunks) { - cache = []; - const pluginOptions = this.options; - const files = pluginOptions.filesOrder - ? pluginOptions.filesOrder(chunk, chunksFiles) - : chunksFiles[chunk.name]; - if ( - (!pluginOptions.blacklistedChunks || pluginOptions.blacklistedChunks.indexOf(chunk.name) < 0) && - files.length > 0 - ) { - // eslint-disable-next-line no-unused-vars - const promise = new Promise((resolve, reject) => { - const usedContext = files.length > 0 ? sassLoader.entries[files[0]].ctx : undefined; - const promise = new Promise(processAsset(files)); - - promise.then( - manageContent(pluginOptions, usedContext, compilation, chunk, resolve, callback), - (error) => { - callback(`SCSS dependencies error, ${error}`); - }, - ); - }); - await Promise.all([promise]); - } - } - callback(); - }); - } -} - -module.exports = SassPlugin; diff --git a/buildtools/webpack.scss-loader.js b/buildtools/webpack.scss-loader.js deleted file mode 100644 index a70b44eab69e..000000000000 --- a/buildtools/webpack.scss-loader.js +++ /dev/null @@ -1,82 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2018-2024 Camptocamp SA -// -// 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. - -'use strict'; - -const entries = {}; - -const loaderUtils = require('loader-utils'); -const path = require('path'); - -/** - * @param transformers - */ -function createTransformersMap(transformers) { - if (!transformers) { - return {}; - } - - // return map of extension strings to transformer functions - return transformers.reduce((extensionMap, transformer) => { - transformer.extensions.forEach((ext) => { - extensionMap[ext] = transformer.transform; - }); - return extensionMap; - }, {}); -} - -/** - * @param ctx - */ -function getLoaderConfig(ctx) { - const options = loaderUtils.getOptions(ctx) || {}; - const includePaths = options.includePaths || []; - const basedir = ctx.rootContext || options.context || ctx.options.context || process.cwd(); - const transformers = createTransformersMap(options.transformers); - - // convert relative to absolute - for (let i = 0; i < includePaths.length; i++) { - if (!path.isAbsolute(includePaths[i])) { - includePaths[i] = path.join(basedir, includePaths[i]); - } - } - - return { - basedir: basedir, - includePaths: includePaths, - transformers: transformers, - baseEntryDir: path.dirname(ctx.resourcePath), - root: options.root, - data: options.data, - }; -} - -module.exports = function (content) { - entries[this.resourcePath] = { - 'content': content, - 'options': getLoaderConfig(this), - 'ctx': this, - }; - this.dependency(this.resourcePath); - return ''; -}; - -module.exports.entries = entries; diff --git a/contribs/gmf/apps/desktop/Controller.js b/contribs/gmf/apps/desktop/Controller.js index 0ce075231bec..d8e86c0fa9df 100644 --- a/contribs/gmf/apps/desktop/Controller.js +++ b/contribs/gmf/apps/desktop/Controller.js @@ -27,7 +27,7 @@ */ import './sass/desktop.scss'; -import './sass/vars_desktop.scss'; + import angular from 'angular'; import {isEventUsingCtrlKey} from 'ngeo/utils'; import gmfControllersAbstractDesktopController, { diff --git a/contribs/gmf/apps/desktop/sass/desktop.scss b/contribs/gmf/apps/desktop/sass/desktop.scss index f0a9c7baad28..ff0293a7872b 100644 --- a/contribs/gmf/apps/desktop/sass/desktop.scss +++ b/contribs/gmf/apps/desktop/sass/desktop.scss @@ -21,6 +21,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import './vars_desktop.scss'; +@import 'gmf/controllers/desktop.scss'; + header { .logo { background-image: url('../image/logo.png'); diff --git a/contribs/gmf/apps/desktop_alt/Controller.js b/contribs/gmf/apps/desktop_alt/Controller.js index 90317c715d4a..5283fbe92aa2 100644 --- a/contribs/gmf/apps/desktop_alt/Controller.js +++ b/contribs/gmf/apps/desktop_alt/Controller.js @@ -27,7 +27,7 @@ */ import './sass/desktop_alt.scss'; -import './sass/vars_desktop_alt.scss'; + import angular from 'angular'; import gmfControllersAbstractDesktopController, { AbstractDesktopController, diff --git a/contribs/gmf/apps/desktop_alt/sass/desktop_alt.scss b/contribs/gmf/apps/desktop_alt/sass/desktop_alt.scss index ebc681d277d4..6a2a6eff28b7 100644 --- a/contribs/gmf/apps/desktop_alt/sass/desktop_alt.scss +++ b/contribs/gmf/apps/desktop_alt/sass/desktop_alt.scss @@ -21,6 +21,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import './vars_desktop_alt.scss'; +@import 'gmf/controllers/desktop.scss'; +@import '~mapillary-js/dist/mapillary.css'; + html { body { padding: 0; @@ -57,7 +61,7 @@ header { div .ngeo-displaywindow { $displaywindow-min-height: 15rem; - left: $app-margin + $left-panel-width + $displaywindow-min-height / 2; + left: calc($app-margin + $left-panel-width + $displaywindow-min-height / 2); right: initial; top: $topbar-height + $app-margin + 3 * $map-tools-size; } diff --git a/contribs/gmf/apps/iframe_api/Controller.js b/contribs/gmf/apps/iframe_api/Controller.js index bea6af10964e..bb97eb8cc263 100644 --- a/contribs/gmf/apps/iframe_api/Controller.js +++ b/contribs/gmf/apps/iframe_api/Controller.js @@ -26,8 +26,7 @@ * by the HTML page and the controller to provide the configuration. */ -import 'gmf/controllers/iframe_api.scss'; -import 'gmf/controllers/vars_desktop.scss'; +import './sass/iframe_api.scss'; import angular from 'angular'; import gmfControllersAbstractAPIController, { diff --git a/examples/common_dependencies.scss b/contribs/gmf/apps/iframe_api/sass/iframe_api.scss similarity index 92% rename from examples/common_dependencies.scss rename to contribs/gmf/apps/iframe_api/sass/iframe_api.scss index e6af595c3a38..08aa5a98ab89 100644 --- a/examples/common_dependencies.scss +++ b/contribs/gmf/apps/iframe_api/sass/iframe_api.scss @@ -21,4 +21,5 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -$fa-font-path: '~@fortawesome/fontawesome-free/webfonts'; +@import 'gmf/controllers/vars_desktop.scss'; +@import 'gmf/controllers/iframe_api.scss'; diff --git a/contribs/gmf/apps/mobile/Controller.js b/contribs/gmf/apps/mobile/Controller.js index 1350eae19511..d62b766ed5f8 100644 --- a/contribs/gmf/apps/mobile/Controller.js +++ b/contribs/gmf/apps/mobile/Controller.js @@ -26,7 +26,6 @@ * by the HTML page and the controller to provide the configuration. */ -import './sass/vars_mobile.scss'; import './sass/mobile.scss'; import angular from 'angular'; diff --git a/contribs/gmf/apps/mobile/sass/mobile.scss b/contribs/gmf/apps/mobile/sass/mobile.scss index c32769ae97f4..9d6c9fe1df34 100644 --- a/contribs/gmf/apps/mobile/sass/mobile.scss +++ b/contribs/gmf/apps/mobile/sass/mobile.scss @@ -21,6 +21,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import './vars_mobile.scss'; +@import 'gmf/controllers/mobile.scss'; + gmf-displayquerywindow { position: inherit; diff --git a/contribs/gmf/apps/mobile_alt/Controller.js b/contribs/gmf/apps/mobile_alt/Controller.js index d5884a4508ba..daef0ab36293 100644 --- a/contribs/gmf/apps/mobile_alt/Controller.js +++ b/contribs/gmf/apps/mobile_alt/Controller.js @@ -26,7 +26,6 @@ * by the HTML page and the controller to provide the configuration. */ -import './sass/vars_mobile_alt.scss'; import './sass/mobile_alt.scss'; import angular from 'angular'; diff --git a/contribs/gmf/apps/mobile_alt/sass/mobile_alt.scss b/contribs/gmf/apps/mobile_alt/sass/mobile_alt.scss index 7d06b6535260..142aba635997 100644 --- a/contribs/gmf/apps/mobile_alt/sass/mobile_alt.scss +++ b/contribs/gmf/apps/mobile_alt/sass/mobile_alt.scss @@ -21,6 +21,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import './vars_mobile_alt.scss'; +@import 'gmf/controllers/mobile.scss'; + #themes .gmf-theme-selector { display: flex; flex-wrap: wrap; diff --git a/contribs/gmf/apps/oeedit/Controller.js b/contribs/gmf/apps/oeedit/Controller.js index 21a92d8d2275..4a512d4ace13 100644 --- a/contribs/gmf/apps/oeedit/Controller.js +++ b/contribs/gmf/apps/oeedit/Controller.js @@ -26,7 +26,6 @@ * by the HTML page and the controller to provide the configuration. */ -import './sass/vars_oeedit.scss'; import './sass/oeedit.scss'; import angular from 'angular'; import gmfControllersAbstractDesktopController, { diff --git a/contribs/gmf/apps/oeedit/sass/oeedit.scss b/contribs/gmf/apps/oeedit/sass/oeedit.scss index fcd217de4c31..0939cb721f34 100644 --- a/contribs/gmf/apps/oeedit/sass/oeedit.scss +++ b/contribs/gmf/apps/oeedit/sass/oeedit.scss @@ -21,6 +21,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import './vars_oeedit.scss'; +@import 'gmf/controllers/desktop.scss'; + header { .logo { background-image: url('../image/logo.png'); diff --git a/contribs/gmf/examples/backgroundlayerselector.js b/contribs/gmf/examples/backgroundlayerselector.js index 6b6ccdfe3c90..120f6eab0be1 100644 --- a/contribs/gmf/examples/backgroundlayerselector.js +++ b/contribs/gmf/examples/backgroundlayerselector.js @@ -20,8 +20,10 @@ MainController.$inject = ['gmfThemes']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './backgroundlayerselector.css'; + +import angular from 'angular'; import gmfBackgroundlayerselectorModule from 'gmf/backgroundlayerselector/module'; import gmfMapComponent from 'gmf/map/component'; import gmfThemeThemes from 'gmf/theme/Themes'; diff --git a/contribs/gmf/examples/common_dependencies.js b/contribs/gmf/examples/common_dependencies.js index a850306541b3..b1af9f253f31 100644 --- a/contribs/gmf/examples/common_dependencies.js +++ b/contribs/gmf/examples/common_dependencies.js @@ -19,15 +19,11 @@ // 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. -import 'gmf/sass/vars.scss'; import 'jquery'; import 'angular'; import 'angular-gettext'; import 'bootstrap'; -import 'ol/ol.css'; -import 'bootstrap/dist/css/bootstrap.css'; - /* * Auto redirect to https to prevent CORS exceptions */ diff --git a/contribs/gmf/examples/common_styles.scss b/contribs/gmf/examples/common_styles.scss new file mode 100644 index 000000000000..2de1664f2761 --- /dev/null +++ b/contribs/gmf/examples/common_styles.scss @@ -0,0 +1,8 @@ +@import 'ol/ol.css'; +@import 'bootstrap/dist/css/bootstrap.css'; +@import 'ngeo/sass/vars.scss'; +@import 'ngeo/sass/vars_only.scss'; +@import './vars.scss'; +@import 'ngeo/sass/typeahead.scss'; +@import 'ngeo/sass/jquery-ui.scss'; +@import 'ngeo/sass/font.scss'; diff --git a/contribs/gmf/examples/contextualdata.js b/contribs/gmf/examples/contextualdata.js index 8d34b341a088..746fbd49f457 100644 --- a/contribs/gmf/examples/contextualdata.js +++ b/contribs/gmf/examples/contextualdata.js @@ -19,8 +19,11 @@ // 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. -import angular from 'angular'; +import './common_styles.scss'; +import 'ngeo/contextualdata/contextualdata.scss'; import './contextualdata.css'; + +import angular from 'angular'; import gmfContextualdataModule from 'gmf/contextualdata/module'; import gmfMapComponent from 'gmf/map/component'; import ngeoMiscFilters from 'ngeo/misc/filters'; diff --git a/contribs/gmf/examples/datepicker.js b/contribs/gmf/examples/datepicker.js index ae7053fa9e6f..4ebd79c23ff8 100644 --- a/contribs/gmf/examples/datepicker.js +++ b/contribs/gmf/examples/datepicker.js @@ -20,8 +20,10 @@ MainController.$inject = ['ngeoWMSTime']; // 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. -import angular from 'angular'; import './datepicker.css'; +import './common_styles.scss'; + +import angular from 'angular'; import ngeoMiscDatepickerComponent from 'ngeo/misc/datepickerComponent'; import ngeoMiscWMSTime from 'ngeo/misc/WMSTime'; import {TimePropertyWidgetEnum, TimePropertyResolutionEnum, TimePropertyModeEnum} from 'ngeo/datasource/OGC'; diff --git a/contribs/gmf/examples/displayquerygrid.js b/contribs/gmf/examples/displayquerygrid.js index 6c532112257a..70b08ea63150 100644 --- a/contribs/gmf/examples/displayquerygrid.js +++ b/contribs/gmf/examples/displayquerygrid.js @@ -21,9 +21,11 @@ QueryresultController.$inject = ['ngeoQueryResult']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './displayquerygrid.css'; import './gmf-hidden.inc.css'; + +import angular from 'angular'; import gmfDatasourceManager from 'gmf/datasource/Manager'; import gmfLayertreeComponent from 'gmf/layertree/component'; import gmfMapComponent from 'gmf/map/component'; diff --git a/contribs/gmf/examples/displayquerywindow.js b/contribs/gmf/examples/displayquerywindow.js index 2f45c5618585..c1f4ce201a51 100644 --- a/contribs/gmf/examples/displayquerywindow.js +++ b/contribs/gmf/examples/displayquerywindow.js @@ -21,9 +21,11 @@ QueryresultController.$inject = ['ngeoQueryResult']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './displayquerywindow.css'; import './gmf-hidden.inc.css'; + +import angular from 'angular'; import gmfDatasourceManager from 'gmf/datasource/Manager'; import gmfLayertreeComponent from 'gmf/layertree/component'; import gmfMapComponent from 'gmf/map/component'; diff --git a/contribs/gmf/examples/drawfeature.js b/contribs/gmf/examples/drawfeature.js index b29075d0297b..819019413830 100644 --- a/contribs/gmf/examples/drawfeature.js +++ b/contribs/gmf/examples/drawfeature.js @@ -20,8 +20,10 @@ MainController.$inject = ['$scope', 'ngeoFeatureHelper', 'ngeoFeatures', 'ngeoTo // 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. -import angular from 'angular'; +import './common_styles.scss'; import './drawfeature.css'; + +import angular from 'angular'; import 'bootstrap/js/src/tooltip'; import gmfMapComponent from 'gmf/map/component'; import ngeoMapFeatureOverlayMgr from 'ngeo/map/FeatureOverlayMgr'; diff --git a/contribs/gmf/examples/elevation.js b/contribs/gmf/examples/elevation.js index 3f34bb9e2ef4..5c738a9c8b60 100644 --- a/contribs/gmf/examples/elevation.js +++ b/contribs/gmf/examples/elevation.js @@ -19,8 +19,10 @@ // 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. -import angular from 'angular'; +import './common_styles.scss'; import './elevation.css'; + +import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import gmfRasterModule from 'gmf/raster/module'; import EPSG2056 from 'ngeo/proj/EPSG_2056'; diff --git a/contribs/gmf/examples/featurestyle.js b/contribs/gmf/examples/featurestyle.js index 31e84163cf7c..809c7acc9c4a 100644 --- a/contribs/gmf/examples/featurestyle.js +++ b/contribs/gmf/examples/featurestyle.js @@ -20,8 +20,10 @@ MainController.$inject = ['$scope', 'ngeoFeatureHelper']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './featurestyle.css'; + +import angular from 'angular'; import gmfDrawingFeatureStyleComponent from 'gmf/drawing/featureStyleComponent'; import gmfMapComponent from 'gmf/map/component'; import ngeoFormatFeatureProperties from 'ngeo/format/FeatureProperties'; diff --git a/contribs/gmf/examples/importdatasource.js b/contribs/gmf/examples/importdatasource.js index 32aa52d6a695..a0dcfd52c5e1 100644 --- a/contribs/gmf/examples/importdatasource.js +++ b/contribs/gmf/examples/importdatasource.js @@ -19,9 +19,13 @@ // 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. +import 'ngeo/layertree/common.scss'; +import 'ngeo/layertree/timeslider.scss'; +import './common_styles.scss'; +import './importdatasource.css'; + // Todo - use the 'Filter' theme instead if the 'Edit' theme import angular from 'angular'; -import './importdatasource.css'; import 'bootstrap/js/src/tooltip'; import gmfDatasourceManager from 'gmf/datasource/Manager'; import gmfImportImportdatasourceComponent from 'gmf/import/importdatasourceComponent'; diff --git a/contribs/gmf/examples/layertree.js b/contribs/gmf/examples/layertree.js index f205ad1dc6a5..d83d4ec6fff2 100644 --- a/contribs/gmf/examples/layertree.js +++ b/contribs/gmf/examples/layertree.js @@ -20,8 +20,12 @@ MainController.$inject = ['gmfTreeManager', 'gmfThemes', 'gmfThemeManager', 'nge // 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. -import angular from 'angular'; +import 'ngeo/layertree/common.scss'; +import 'ngeo/layertree/timeslider.scss'; +import './common_styles.scss'; import './layertree.css'; + +import angular from 'angular'; import gmfDisclaimerModule from 'gmf/disclaimer/module'; import gmfLayertreeComponent from 'gmf/layertree/component'; import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager'; diff --git a/contribs/gmf/examples/layertreeadd.js b/contribs/gmf/examples/layertreeadd.js index bb672ebdd7ec..7652a5168714 100644 --- a/contribs/gmf/examples/layertreeadd.js +++ b/contribs/gmf/examples/layertreeadd.js @@ -20,8 +20,12 @@ MainController.$inject = ['gmfTreeManager', 'gmfThemes', 'gmfThemeManager', 'nge // 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. -import angular from 'angular'; +import 'ngeo/layertree/common.scss'; +import 'ngeo/layertree/timeslider.scss'; +import './common_styles.scss'; import './layertreeadd.css'; + +import angular from 'angular'; import gmfDisclaimerModule from 'gmf/disclaimer/module'; import gmfLayertreeComponent from 'gmf/layertree/component'; import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager'; diff --git a/contribs/gmf/examples/mobilemeasure.js b/contribs/gmf/examples/mobilemeasure.js index 2401a9df9fc6..a3f2b7768ef9 100644 --- a/contribs/gmf/examples/mobilemeasure.js +++ b/contribs/gmf/examples/mobilemeasure.js @@ -20,8 +20,10 @@ MainController.$inject = ['gmfPermalink']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './mobilemeasure.css'; + +import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import gmfPermalinkPermalink from 'gmf/permalink/Permalink'; import gmfMobileMeasureAreaComponent from 'gmf/mobile/measure/areaComponent'; diff --git a/contribs/gmf/examples/mouseposition.js b/contribs/gmf/examples/mouseposition.js index 393f1f645d94..8bb302f7daad 100644 --- a/contribs/gmf/examples/mouseposition.js +++ b/contribs/gmf/examples/mouseposition.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './mouseposition.css'; + import angular from 'angular'; import gmfMapModule from 'gmf/map/module'; import gmfMapComponent from 'gmf/map/component'; diff --git a/contribs/gmf/examples/objectediting.js b/contribs/gmf/examples/objectediting.js index 48cd79ebfa57..b64595100cdd 100644 --- a/contribs/gmf/examples/objectediting.js +++ b/contribs/gmf/examples/objectediting.js @@ -20,8 +20,10 @@ MainController.$inject = ['gmfObjectEditingManager', 'gmfThemes', 'gmfTreeManage // 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. -import angular from 'angular'; +import './common_styles.scss'; import './objectediting.css'; + +import angular from 'angular'; import gmfLayertreeComponent from 'gmf/layertree/component'; import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager'; import gmfMapComponent from 'gmf/map/component'; diff --git a/contribs/gmf/examples/objecteditinghub.js b/contribs/gmf/examples/objecteditinghub.js index 88164a0ac4ae..9b9a8830443b 100644 --- a/contribs/gmf/examples/objecteditinghub.js +++ b/contribs/gmf/examples/objecteditinghub.js @@ -20,8 +20,10 @@ MainController.$inject = ['$http', '$q', '$scope', 'gmfThemes', 'gmfXSDAttribute // 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. -import angular from 'angular'; +import './common_styles.scss'; import './objecteditinghub.css'; + +import angular from 'angular'; import gmfEditingXSDAttributes from 'gmf/editing/XSDAttributes'; import gmfObjecteditingManager, {ObjecteditingParam} from 'gmf/objectediting/Manager'; import gmfThemeThemes from 'gmf/theme/Themes'; diff --git a/contribs/gmf/examples/options.js b/contribs/gmf/examples/options.js index ef380cda9eb7..1587ea3ab6d6 100644 --- a/contribs/gmf/examples/options.js +++ b/contribs/gmf/examples/options.js @@ -19,8 +19,6 @@ // 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. -import './vars.scss'; - /** * Base url for the GeoMapFish demo server. * diff --git a/contribs/gmf/examples/permalink.js b/contribs/gmf/examples/permalink.js index 562649f366c7..cea291753879 100644 --- a/contribs/gmf/examples/permalink.js +++ b/contribs/gmf/examples/permalink.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './permalink.css'; + import angular from 'angular'; import gmfMapModule from 'gmf/map/module'; import gmfMapComponent from 'gmf/map/component'; diff --git a/contribs/gmf/examples/print.js b/contribs/gmf/examples/print.js index 4de443ae0883..f7870b016a04 100644 --- a/contribs/gmf/examples/print.js +++ b/contribs/gmf/examples/print.js @@ -20,9 +20,11 @@ MainController.$inject = ['gmfThemes']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './print.css'; import './gmf-hidden.inc.css'; + +import angular from 'angular'; import gmfLayertreeComponent from 'gmf/layertree/component'; import gmfMapComponent from 'gmf/map/component'; import gmfPrintComponent from 'gmf/print/component'; diff --git a/contribs/gmf/examples/profile.js b/contribs/gmf/examples/profile.js index f64e86510739..720c4ade6ea0 100644 --- a/contribs/gmf/examples/profile.js +++ b/contribs/gmf/examples/profile.js @@ -20,8 +20,11 @@ MainController.$inject = ['$scope']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './profile.css'; +import 'ngeo/profile/profile.scss'; + +import angular from 'angular'; import gmfPermalinkPermalink from 'gmf/permalink/Permalink'; import gmfMapComponent from 'gmf/map/component'; import ngeoMapFeatureOverlayMgr from 'ngeo/map/FeatureOverlayMgr'; diff --git a/contribs/gmf/examples/search.js b/contribs/gmf/examples/search.js index bac3ce435878..3629fdde9fe7 100644 --- a/contribs/gmf/examples/search.js +++ b/contribs/gmf/examples/search.js @@ -20,8 +20,11 @@ MainController.$inject = ['gmfThemes']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './search.css'; +import 'ngeo/search/search.scss'; + +import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import ngeoMapFeatureOverlayMgr from 'ngeo/map/FeatureOverlayMgr'; import gmfSearchModule from 'gmf/search/module'; diff --git a/contribs/gmf/examples/share.js b/contribs/gmf/examples/share.js index 9f158790f398..ae95f9c6d9f0 100644 --- a/contribs/gmf/examples/share.js +++ b/contribs/gmf/examples/share.js @@ -19,8 +19,10 @@ // 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. -import angular from 'angular'; +import './common_styles.scss'; import './share.css'; + +import angular from 'angular'; import gmfPermalinkShareComponent from 'gmf/permalink/shareComponent'; import ngeoMessageModalComponent from 'ngeo/message/modalComponent'; import options from './options'; diff --git a/contribs/gmf/examples/simple.js b/contribs/gmf/examples/simple.js index abd8600799be..13efe044bbb2 100644 --- a/contribs/gmf/examples/simple.js +++ b/contribs/gmf/examples/simple.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './simple.css'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import ngeoMapModule from 'ngeo/map/module'; diff --git a/contribs/gmf/examples/themeselector.js b/contribs/gmf/examples/themeselector.js index 43da56513dff..7f08a834ea5f 100644 --- a/contribs/gmf/examples/themeselector.js +++ b/contribs/gmf/examples/themeselector.js @@ -20,8 +20,10 @@ MainController.$inject = ['$http', 'gmfThemes', 'gmfThemeManager']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './themeselector.css'; + +import angular from 'angular'; import gmfThemeModule from 'gmf/theme/module'; import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager'; import options from './options'; diff --git a/contribs/gmf/examples/timeslider.js b/contribs/gmf/examples/timeslider.js index ab1edf7633d5..391fdb6c7ae0 100644 --- a/contribs/gmf/examples/timeslider.js +++ b/contribs/gmf/examples/timeslider.js @@ -20,7 +20,10 @@ MainController.$inject = ['$scope', 'ngeoWMSTime']; // 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. +import 'ngeo/layertree/timeslider.scss'; +import './common_styles.scss'; import './timeslider.css'; + import angular from 'angular'; import gmfLayertreeTimeSliderComponent from 'gmf/layertree/timeSliderComponent'; import ngeoMiscWMSTime from 'ngeo/misc/WMSTime'; diff --git a/contribs/gmf/examples/wfspermalink.js b/contribs/gmf/examples/wfspermalink.js index 61a3b72a7854..cbcba3241859 100644 --- a/contribs/gmf/examples/wfspermalink.js +++ b/contribs/gmf/examples/wfspermalink.js @@ -19,8 +19,10 @@ // 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. -import angular from 'angular'; +import './common_styles.scss'; import './wfspermalink.css'; + +import angular from 'angular'; import gmfMapModule from 'gmf/map/module'; import gmfMapComponent from 'gmf/map/component'; import gmfQueryWindowComponent from 'gmf/query/windowComponent'; diff --git a/contribs/gmf/examples/xsdattributes.js b/contribs/gmf/examples/xsdattributes.js index 80166c48cc2c..5b360b318a40 100644 --- a/contribs/gmf/examples/xsdattributes.js +++ b/contribs/gmf/examples/xsdattributes.js @@ -20,14 +20,15 @@ MainController.$inject = ['$timeout', 'gmfThemes', 'gmfXSDAttributes']; // 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. -import angular from 'angular'; +import './common_styles.scss'; import './xsdattributes.css'; + +import angular from 'angular'; import gmfThemeThemes from 'gmf/theme/Themes'; import gmfEditingXSDAttributes from 'gmf/editing/XSDAttributes'; import ngeoEditingAttributesComponent from 'ngeo/editing/attributesComponent'; import {getGeometryAttribute} from 'ngeo/format/XSDAttribute'; import olFeature from 'ol/Feature'; -import 'jquery-datetimepicker/jquery.datetimepicker.css'; import options from './options'; /** @type {angular.IModule} **/ diff --git a/docs/guidelines.md b/docs/guidelines.md index 478ac6120547..e258246be8f6 100644 --- a/docs/guidelines.md +++ b/docs/guidelines.md @@ -391,20 +391,21 @@ We choose units that don't depend on parent tags and are relative. ### CSS variable -Note: Not supported by IE - Now it's possible to configure some variable in the CSS to make the variable, -they should be defined and used like that (with backward compatilility for IE): +they should be defined and used like that: - In the `src/sass/vars_only.scss` file: `$my-variable: ... !default;`. +- In a `scss` file importing `vars_only.scss`, if you want to redefine the default (import after definition): + `$my-variable: ... !default;`. + `@import ngeo/sass/vars_only.scss`. - In the `sass/vars.scss` file, in the `:root` section: `--my-variable: #{$my-variable};`. - In your scss file: `the-css-property: $my-css-variable;`, `the-css-property: var(--my-css-variable);`. -All collors calculated from `brand-primary` and `brand-secoundary` should be exposed as variable, and they should also be calculates in the `src/controllers/calculateCssVars.js` file. +All colors calculated from `brand-primary` and `brand-secoundary` should be exposed as variable, and they should also be calculates in the `src/controllers/calculateCssVars.js` file. ## Property renaming diff --git a/examples/animation.js b/examples/animation.js index 6295c57acc7f..366ddc42394e 100644 --- a/examples/animation.js +++ b/examples/animation.js @@ -20,7 +20,9 @@ MainController.$inject = ['$timeout']; // 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. +import './common_styles.scss'; import './animation.css'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/asitvd.js b/examples/asitvd.js index e5a66be10742..917911d93c58 100644 --- a/examples/asitvd.js +++ b/examples/asitvd.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import ngeoSourceAsitVD from 'ngeo/source/AsitVD'; import EPSG2056 from 'ngeo/proj/EPSG_2056'; diff --git a/examples/attributes.js b/examples/attributes.js index 62f227bd0418..ebef39c63ae7 100644 --- a/examples/attributes.js +++ b/examples/attributes.js @@ -20,6 +20,8 @@ MainController.$inject = ['$http', '$timeout', '$scope']; // 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. +import './common_styles.scss'; + import angular from 'angular'; import ngeoFormatXSDAttribute from 'ngeo/format/XSDAttribute'; import ngeoEditingAttributesComponent from 'ngeo/editing/attributesComponent'; diff --git a/examples/backgroundlayer.js b/examples/backgroundlayer.js index d8661e064176..b718bbb46f8a 100644 --- a/examples/backgroundlayer.js +++ b/examples/backgroundlayer.js @@ -21,7 +21,9 @@ BackgroundlayerController.$inject = ['$http', 'ngeoBackgroundLayerMgr']; // 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. +import './common_styles.scss'; import './backgroundlayer.css'; + import angular from 'angular'; import ngeoSourceAsitVD from 'ngeo/source/AsitVD'; import {MAPSERVER_PROXY} from './url'; diff --git a/examples/backgroundlayerdropdown.js b/examples/backgroundlayerdropdown.js index 92366f885adf..ae0ed068e1c4 100644 --- a/examples/backgroundlayerdropdown.js +++ b/examples/backgroundlayerdropdown.js @@ -21,7 +21,9 @@ BackgroundlayerController.$inject = ['$http', 'ngeoBackgroundLayerMgr']; // 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. +import './common_styles.scss'; import './backgroundlayerdropdown.css'; + import angular from 'angular'; import ngeoSourceAsitVD from 'ngeo/source/AsitVD'; import {MAPSERVER_PROXY} from './url'; diff --git a/examples/colorpicker.js b/examples/colorpicker.js index c5b4d4576623..ce33532dbc70 100644 --- a/examples/colorpicker.js +++ b/examples/colorpicker.js @@ -20,7 +20,9 @@ MainController.$inject = ['$scope']; // 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. +import './common_styles.scss'; import './colorpicker.css'; + import angular from 'angular'; import ngeoMiscColorpickerComponent from 'ngeo/misc/colorpickerComponent'; diff --git a/examples/common_dependencies.js b/examples/common_dependencies.js index 542190ee21c8..33007e9fd69f 100644 --- a/examples/common_dependencies.js +++ b/examples/common_dependencies.js @@ -19,16 +19,10 @@ // 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. -import './common_dependencies.scss'; -import './base.css'; import 'jquery'; import 'angular'; import 'angular-gettext'; import 'bootstrap'; - -import 'ol/ol.css'; -import 'bootstrap/dist/css/bootstrap.css'; - /* * Auto redirect to https to prevent CORS exceptions */ diff --git a/examples/common_styles.scss b/examples/common_styles.scss new file mode 100644 index 000000000000..c9538178ad7e --- /dev/null +++ b/examples/common_styles.scss @@ -0,0 +1,7 @@ +@import 'ol/ol.css'; +@import 'ngeo/sass/font.scss'; +@import 'bootstrap/dist/css/bootstrap.css'; +@import 'ngeo/sass/typeahead.scss'; +@import 'ngeo/sass/jquery-ui.scss'; +@import './vars.scss'; +@import './base.css'; diff --git a/examples/control.js b/examples/control.js index d640f3d54902..11a275536481 100644 --- a/examples/control.js +++ b/examples/control.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; diff --git a/examples/createfeature.js b/examples/createfeature.js index a2eac254fdab..f59fb4c914e4 100644 --- a/examples/createfeature.js +++ b/examples/createfeature.js @@ -20,7 +20,9 @@ MainController.$inject = ['ngeoToolActivateMgr']; // 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. +import './common_styles.scss'; import './createfeature.css'; + import angular from 'angular'; import ngeoEditingCreatefeatureComponent from 'ngeo/editing/createfeatureComponent'; import ngeoGeometryType from 'ngeo/GeometryType'; diff --git a/examples/datepicker.js b/examples/datepicker.js index f80b6153d379..4f56bae40b34 100644 --- a/examples/datepicker.js +++ b/examples/datepicker.js @@ -21,6 +21,8 @@ MainController.$inject = ['ngeoTime']; // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import './datepicker.css'; +import './common_styles.scss'; + import angular from 'angular'; import ngeoMiscDatepickerComponent from 'ngeo/misc/datepickerComponent'; import ngeoMiscTime from 'ngeo/misc/Time'; diff --git a/examples/datetimepicker.js b/examples/datetimepicker.js index a3cc6ee575cf..299d08327a45 100644 --- a/examples/datetimepicker.js +++ b/examples/datetimepicker.js @@ -19,7 +19,10 @@ // 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. +import './common_styles.scss'; import './datetimepicker.scss'; +import 'jquery-datetimepicker/jquery.datetimepicker.css'; + import angular from 'angular'; import ngeoMiscDatetimepickerComponent from 'ngeo/misc/datetimepickerComponent'; diff --git a/examples/disclaimer.js b/examples/disclaimer.js index 50a4ef07c870..cd4861c39112 100644 --- a/examples/disclaimer.js +++ b/examples/disclaimer.js @@ -20,7 +20,9 @@ MainController.$inject = ['ngeoDisclaimer']; // 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. +import './common_styles.scss'; import './disclaimer.css'; + import 'bootstrap/js/src/tooltip'; import angular from 'angular'; import ngeoMessageDisclaimer from 'ngeo/message/Disclaimer'; diff --git a/examples/displaywindow.js b/examples/displaywindow.js index 3db9cadbdc82..05718b86958e 100644 --- a/examples/displaywindow.js +++ b/examples/displaywindow.js @@ -20,7 +20,9 @@ MainController.$inject = ['$scope']; // 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. +import './common_styles.scss'; import './displaywindow.css'; + import angular from 'angular'; import ngeoMessageDisplaywindowComponent from 'ngeo/message/displaywindowComponent'; diff --git a/examples/drawfeature.js b/examples/drawfeature.js index 45e78a5cb6fc..04545a7a7d71 100644 --- a/examples/drawfeature.js +++ b/examples/drawfeature.js @@ -20,7 +20,9 @@ MainController.$inject = ['$scope', 'ngeoFeatures', 'ngeoToolActivateMgr']; // 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. +import './common_styles.scss'; import './drawfeature.css'; + import angular from 'angular'; import ngeoDrawModule from 'ngeo/draw/module'; import gmfMapComponent from 'gmf/map/component'; diff --git a/examples/elevationProfile.js b/examples/elevationProfile.js index d94b26eb0751..ed2b9b467671 100644 --- a/examples/elevationProfile.js +++ b/examples/elevationProfile.js @@ -20,7 +20,9 @@ MainController.$inject = ['$http', '$scope']; // 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. +import './common_styles.scss'; import './elevationProfile.css'; + import angular from 'angular'; import EPSG2056 from 'ngeo/proj/EPSG_2056'; import {MAPSERVER_PROXY} from './url'; diff --git a/examples/error.js b/examples/error.js index c4c21ae41473..cfc16a072b3a 100644 --- a/examples/error.js +++ b/examples/error.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/googlestreetview.js b/examples/googlestreetview.js index 959c7d364870..8ec95c32b1dc 100644 --- a/examples/googlestreetview.js +++ b/examples/googlestreetview.js @@ -20,7 +20,9 @@ MainController.$inject = ['ngeoToolActivateMgr']; // 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. +import './common_styles.scss'; import './googlestreetview.css'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/grid.js b/examples/grid.js index d09306058a53..555aa2d62b67 100644 --- a/examples/grid.js +++ b/examples/grid.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './grid.css'; + import angular from 'angular'; import ngeoGridConfig from 'ngeo/grid/Config'; import ngeoGridModule from 'ngeo/grid/module'; diff --git a/examples/importfeatures.js b/examples/importfeatures.js index 7ba36d5af9fe..bcb125b4733b 100644 --- a/examples/importfeatures.js +++ b/examples/importfeatures.js @@ -20,6 +20,8 @@ MainController.$inject = ['$scope']; // 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. +import './common_styles.scss'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; diff --git a/examples/interactionbtngroup.js b/examples/interactionbtngroup.js index e9a5cfbbbd54..1d2974bfd63e 100644 --- a/examples/interactionbtngroup.js +++ b/examples/interactionbtngroup.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './interactionbtngroup.css'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; diff --git a/examples/layerorder.js b/examples/layerorder.js index dc8f1ed1d52f..769e11871994 100644 --- a/examples/layerorder.js +++ b/examples/layerorder.js @@ -20,7 +20,9 @@ MainController.$inject = ['$scope']; // 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. +import './common_styles.scss'; import './layerorder.css'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; diff --git a/examples/locationsearch.js b/examples/locationsearch.js index c5882f035fed..f8c4019f656e 100644 --- a/examples/locationsearch.js +++ b/examples/locationsearch.js @@ -20,7 +20,10 @@ SearchController.$inject = ['ngeoCreateLocationSearchBloodhound']; // 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. +import './common_styles.scss'; import './locationsearch.css'; +import 'ngeo/search/search.scss'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; diff --git a/examples/mapfishprint.js b/examples/mapfishprint.js index 219e02230b0f..621b79331204 100644 --- a/examples/mapfishprint.js +++ b/examples/mapfishprint.js @@ -20,6 +20,8 @@ MainController.$inject = ['$timeout', 'ngeoCreatePrint', 'ngeoPrintUtils']; // 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. +import './common_styles.scss'; + import angular from 'angular'; import {MAPSERVER_PROXY, PRINT_PROXY} from './url'; import EPSG2056 from 'ngeo/proj/EPSG_2056'; diff --git a/examples/mapillarystreetview.js b/examples/mapillarystreetview.js index 0445263bfb82..5b3513d7f337 100644 --- a/examples/mapillarystreetview.js +++ b/examples/mapillarystreetview.js @@ -20,7 +20,10 @@ MainController.$inject = ['ngeoToolActivateMgr']; // 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. +import './common_styles.scss'; import './mapillarystreetview.css'; +import 'mapillary-js/dist/mapillary.css'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/mapswipe.js b/examples/mapswipe.js index 3d7373fb0bad..1c510f166b2d 100644 --- a/examples/mapswipe.js +++ b/examples/mapswipe.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './mapswipe.css'; + import angular from 'angular'; import ngeoMapswipeModule from 'ngeo/map/swipe'; import gmfMapComponent from 'gmf/map/component'; diff --git a/examples/mask.js b/examples/mask.js index c4c21ae41473..cfc16a072b3a 100644 --- a/examples/mask.js +++ b/examples/mask.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/measure.js b/examples/measure.js index 7877b373a77e..6476a40aa191 100644 --- a/examples/measure.js +++ b/examples/measure.js @@ -21,6 +21,8 @@ MeasuretoolsController.$inject = ['$scope', '$compile', '$sce', '$filter', 'gett // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import './measure.css'; +import './common_styles.scss'; + import angular from 'angular'; import ngeoInteractionMeasureArea from 'ngeo/interaction/MeasureArea'; import ngeoInteractionMeasureAzimut from 'ngeo/interaction/MeasureAzimut'; diff --git a/examples/mobilegeolocation.js b/examples/mobilegeolocation.js index e31495154ff8..420c5fa9ff5f 100644 --- a/examples/mobilegeolocation.js +++ b/examples/mobilegeolocation.js @@ -20,7 +20,9 @@ MainController.$inject = ['$scope']; // 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. +import './common_styles.scss'; import './mobilegeolocation.css'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/modal.js b/examples/modal.js index f916b2680c4b..7df4380a66a8 100644 --- a/examples/modal.js +++ b/examples/modal.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import ngeoMessageModalComponent from 'ngeo/message/modalComponent'; diff --git a/examples/modifycircle.js b/examples/modifycircle.js index 087c80e24c2d..45522732978f 100644 --- a/examples/modifycircle.js +++ b/examples/modifycircle.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import ngeoFormatFeatureProperties from 'ngeo/format/FeatureProperties'; import ngeoInteractionModifyCircle from 'ngeo/interaction/ModifyCircle'; diff --git a/examples/modifyrectangle.js b/examples/modifyrectangle.js index 40062befdd27..f9e4029f296c 100644 --- a/examples/modifyrectangle.js +++ b/examples/modifyrectangle.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import ngeoInteractionModifyRectangle from 'ngeo/interaction/ModifyRectangle'; import olMap from 'ol/Map'; diff --git a/examples/notification.js b/examples/notification.js index dccf2bda483a..0cfc3b0da6fd 100644 --- a/examples/notification.js +++ b/examples/notification.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './notification.css'; + import 'bootstrap/js/src/tooltip'; import angular from 'angular'; import {MessageType} from 'ngeo/message/Message'; diff --git a/examples/options.js b/examples/options.js index ef380cda9eb7..1587ea3ab6d6 100644 --- a/examples/options.js +++ b/examples/options.js @@ -19,8 +19,6 @@ // 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. -import './vars.scss'; - /** * Base url for the GeoMapFish demo server. * diff --git a/examples/permalink.js b/examples/permalink.js index 09afbb75f40e..bdfac861de88 100644 --- a/examples/permalink.js +++ b/examples/permalink.js @@ -21,6 +21,8 @@ MapComponentController.$inject = ['ngeoLocation', 'ngeoDebounce']; // 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. +import './common_styles.scss'; + import angular from 'angular'; import ngeoFormatFeatureHash from 'ngeo/format/FeatureHash'; import './permalink.css'; diff --git a/examples/popover.js b/examples/popover.js index 0612209d9b0a..2e1f78967542 100644 --- a/examples/popover.js +++ b/examples/popover.js @@ -19,7 +19,9 @@ // 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. +import './common_styles.scss'; import './popover.css'; + import angular from 'angular'; import ngeoMessagePopoverComponent from 'ngeo/message/popoverComponent'; diff --git a/examples/popupservice.js b/examples/popupservice.js index 6f56d0b57593..4ca379d57131 100644 --- a/examples/popupservice.js +++ b/examples/popupservice.js @@ -20,7 +20,9 @@ MainController.$inject = ['$sce', 'ngeoCreatePopup']; // 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. +import './common_styles.scss'; import './popupservice.css'; + import 'bootstrap/js/src/tooltip'; import angular from 'angular'; import ngeoMessagePopup from 'ngeo/message/Popup'; diff --git a/examples/query.js b/examples/query.js index 25acb12f8ed5..90ff5423df03 100644 --- a/examples/query.js +++ b/examples/query.js @@ -21,6 +21,8 @@ QueryresultController.$inject = ['ngeoQueryResult']; // 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. +import './common_styles.scss'; + import angular from 'angular'; import {MAPSERVER_PROXY, MAPSERVER_WFS_FEATURE_NS} from './url'; import './base.css'; diff --git a/examples/recenter.js b/examples/recenter.js index 12891705d26e..4be14c4315a1 100644 --- a/examples/recenter.js +++ b/examples/recenter.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/rotate.js b/examples/rotate.js index 84a30d531431..46845adedff0 100644 --- a/examples/rotate.js +++ b/examples/rotate.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import ngeoInteractionRotate from 'ngeo/interaction/Rotate'; import olCollection from 'ol/Collection'; diff --git a/examples/routing.js b/examples/routing.js index 71cf51536725..6058887f0944 100644 --- a/examples/routing.js +++ b/examples/routing.js @@ -22,10 +22,10 @@ /** * This example shows the ngeo routing directive. */ +import './common_styles.scss'; +import 'ngeo/routing/routing.scss'; import './routing.css'; -import 'ol/ol.css'; -import 'bootstrap/dist/css/bootstrap.css'; -import '@fortawesome/fontawesome-free/css/fontawesome.min.css'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; diff --git a/examples/scaleselector.js b/examples/scaleselector.js index 57e6644a333a..c8d7d107f095 100644 --- a/examples/scaleselector.js +++ b/examples/scaleselector.js @@ -20,7 +20,9 @@ MainController.$inject = ['$scope']; // 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. +import './common_styles.scss'; import './scaleselector.css'; + import angular from 'angular'; import ngeoScaleSelector from 'ngeo/map/scaleselector'; import olMap from 'ol/Map'; diff --git a/examples/search.js b/examples/search.js index 7313ba2e2608..f608a1caa105 100644 --- a/examples/search.js +++ b/examples/search.js @@ -20,9 +20,12 @@ SearchController.$inject = ['$element', '$rootScope', '$compile', 'ngeoSearchCre // 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. +import './common_styles.scss'; +import './search.css'; +import 'ngeo/search/search.scss'; + import angular from 'angular'; import {SEARCH} from './url'; -import './search.css'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; import {proj as EPSG2056} from 'ngeo/proj/EPSG_2056'; diff --git a/examples/simple.js b/examples/simple.js index c4c21ae41473..cfc16a072b3a 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -19,6 +19,8 @@ // 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. +import './common_styles.scss'; + import angular from 'angular'; import olMap from 'ol/Map'; import olView from 'ol/View'; diff --git a/examples/toolActivate.js b/examples/toolActivate.js index ac61c8e0f4b2..e1afe3c875dd 100644 --- a/examples/toolActivate.js +++ b/examples/toolActivate.js @@ -20,6 +20,8 @@ MainController.$inject = ['ngeoToolActivateMgr']; // 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. +import './common_styles.scss'; + import angular from 'angular'; import gmfMapComponent from 'gmf/map/component'; import options from './options'; diff --git a/src/contextualdata/module.js b/src/contextualdata/module.js index 953de56c729b..04797178083f 100644 --- a/src/contextualdata/module.js +++ b/src/contextualdata/module.js @@ -22,8 +22,6 @@ import angular from 'angular'; import gmfContextualdataComponent from 'gmf/contextualdata/component'; -import './contextualdata.scss'; - /** * @type {angular.IModule} */ diff --git a/src/controllers/AbstractDesktopController.js b/src/controllers/AbstractDesktopController.js index 62047f4c851f..97bf3b58af52 100644 --- a/src/controllers/AbstractDesktopController.js +++ b/src/controllers/AbstractDesktopController.js @@ -52,8 +52,6 @@ import olStyleText from 'ol/style/Text'; import 'gmfapi/index'; import panels from 'gmfapi/store/panels'; import user from 'gmfapi/store/user'; -import 'gmf/controllers/vars_desktop.scss'; -import 'gmf/controllers/desktop.scss'; /** * Desktop application abstract controller. diff --git a/src/controllers/AbstractMobileController.js b/src/controllers/AbstractMobileController.js index 684fd7eeff00..47896d38ac01 100644 --- a/src/controllers/AbstractMobileController.js +++ b/src/controllers/AbstractMobileController.js @@ -28,8 +28,6 @@ import gmfMobileNavigationModule from 'gmf/mobile/navigation/module'; import gmfQueryWindowComponent from 'gmf/query/windowComponent'; import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate'; import user from 'gmfapi/store/user'; -import 'gmf/controllers/vars_mobile.scss'; -import 'gmf/controllers/mobile.scss'; /** * Mobile application abstract controller. diff --git a/src/controllers/desktop.scss b/src/controllers/desktop.scss index 950b101dee6f..13720f9868ff 100644 --- a/src/controllers/desktop.scss +++ b/src/controllers/desktop.scss @@ -25,18 +25,26 @@ * Entry point for all styles required for the desktop application. */ -@import '~gmf/sass/gmf-font.scss'; -@import '~gmf/sass/base.scss'; -@import '~gmf/sass/map.scss'; -@import '~gmf/sass/input-range.scss'; -@import '~gmf/sass/popover.scss'; -@import '~gmf/sass/datepicker.scss'; -@import '~gmf/sass/filters.scss'; -@import '~gmf/sass/fullscreenpopup.scss'; -@import '~gmf/sass/loading-mask.scss'; -@import '~gmf/sass/swipe.scss'; - -@import '~gmf/layertree/desktop.scss'; +@import './vars_desktop.scss'; + +@import '~ol/ol.css'; +@import 'gmf/css/reset.css'; +@import 'gmf/sass/gmf-font.scss'; +@import '~bootstrap/scss/bootstrap.scss'; +@import 'gmf/sass/base.scss'; +@import 'gmf/sass/map.scss'; +@import 'gmf/sass/input-range.scss'; +@import 'gmf/sass/fullscreenpopup.scss'; +@import 'gmf/sass/loading-mask.scss'; +@import 'ngeo/sass/components.scss'; + +@import 'gmf/sass/popover.scss'; +@import 'gmf/sass/datepicker.scss'; +@import 'gmf/sass/filters.scss'; +@import 'gmf/sass/fullscreenpopup.scss'; +@import 'gmf/sass/loading-mask.scss'; +@import 'gmf/sass/swipe.scss'; +@import 'gmf/layertree/desktop.scss'; html, body { @@ -228,7 +236,7 @@ gmf-elevationwidget { left: 50%; $width: 2.5rem; width: $width; - margin-left: -($width / 2); + margin-left: calc(($width / 2) * -1); border-bottom: none; border: $border; border-color: $border-color; @@ -436,7 +444,7 @@ gmf-backgroundlayerselector { color: var(--color-light); padding-bottom: $app-margin; margin-bottom: $app-margin; - margin-top: $grid-gutter-width / 2; + margin-top: calc($grid-gutter-width / 2); border-bottom: 0.06rem solid; border-bottom-color: $color-light; border-bottom-color: var(--color-light); diff --git a/src/controllers/iframe_api.scss b/src/controllers/iframe_api.scss index 002a05f49e07..077eda55127b 100644 --- a/src/controllers/iframe_api.scss +++ b/src/controllers/iframe_api.scss @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -@import '~gmf/controllers/desktop.scss'; +@import 'gmf/controllers/desktop.scss'; body { padding: 0; diff --git a/src/controllers/mobile-nav.scss b/src/controllers/mobile-nav.scss index a9263ebf79b1..2b6e52ca01f9 100644 --- a/src/controllers/mobile-nav.scss +++ b/src/controllers/mobile-nav.scss @@ -21,6 +21,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import 'gmf/sass/vars.scss'; + /** * Styles for mobile navigation menus (side menus). */ diff --git a/src/controllers/mobile.scss b/src/controllers/mobile.scss index 83faa0b6ae29..6844368b8244 100644 --- a/src/controllers/mobile.scss +++ b/src/controllers/mobile.scss @@ -25,19 +25,23 @@ * Entry point for all styles required for the mobile application. */ -@import '~gmf/controllers/vars_mobile.scss'; - -@import '~gmf/sass/gmf-font.scss'; -@import '~gmf/sass/base.scss'; -@import '~gmf/sass/map.scss'; -@import '~gmf/sass/input-range.scss'; -@import '~gmf/sass/fullscreenpopup.scss'; -@import '~gmf/sass/iphone.scss'; -@import '~gmf/sass/loading-mask.scss'; -@import '~gmf/controllers/mobile-nav.scss'; -@import '~gmf/search/mobile.scss'; - -@import '~gmf/layertree/mobile.scss'; +@import './vars_mobile.scss'; + +@import '~ol/ol.css'; +@import 'gmf/css/reset.css'; +@import 'gmf/sass/gmf-font.scss'; +@import '~bootstrap/scss/bootstrap.scss'; +@import 'gmf/sass/base.scss'; +@import 'gmf/sass/map.scss'; +@import 'gmf/sass/input-range.scss'; +@import 'gmf/sass/fullscreenpopup.scss'; +@import 'gmf/sass/loading-mask.scss'; +@import 'ngeo/sass/components.scss'; + +@import 'gmf/sass/iphone.scss'; +@import 'gmf/controllers/mobile-nav.scss'; +@import 'gmf/search/mobile.scss'; +@import 'gmf/layertree/mobile.scss'; /** * Mobile specific css only ! diff --git a/src/controllers/vars_desktop.scss b/src/controllers/vars_desktop.scss index fa23e4299442..cc1708756ef1 100644 --- a/src/controllers/vars_desktop.scss +++ b/src/controllers/vars_desktop.scss @@ -27,10 +27,10 @@ $right-panel-width: 17.5rem !default; $panel-separator-width: 7px !default; $streetview-width: 25rem !default; $topbar-height: 2.8rem !default; -$search-width: 8 * $map-tools-size !default; +$search-width: calc(8 * $map-tools-size) !default; $theme-selector-columns: 2 !default; -$theme-selector-column-width: $left-panel-width / 4 * 3 !default; -$theme-selector-height: 1.5 * $left-panel-width !default; +$theme-selector-column-width: calc($left-panel-width / 4 * 3) !default; +$theme-selector-height: calc(1.5 * $left-panel-width) !default; $app-margin: 0.62rem !default; $half-app-margin: 0.32rem !default; @@ -43,7 +43,8 @@ $search-results-max-height: calc( $notification-width: 12.5rem !default; -@import '~gmf/sass/vars.scss'; +// Define wanted default variables before to import previous default variables. +@import 'gmf/sass/vars.scss'; :root { --theme-selector-columns: #{$theme-selector-columns}; diff --git a/src/controllers/vars_mobile.scss b/src/controllers/vars_mobile.scss index 507c6396b284..9e9f6707bf75 100644 --- a/src/controllers/vars_mobile.scss +++ b/src/controllers/vars_mobile.scss @@ -36,7 +36,8 @@ $nav-bg: white !default; $standard-variation: 15% !default; $back-color: darken($nav-bg, $standard-variation) !default; -@import '~gmf/sass/vars.scss'; +// Define wanted default variables before to import previous default variables. +@import 'gmf/sass/vars.scss'; :root { --back-color: #{$back-color}; diff --git a/src/dropfile/dropfile.scss b/src/dropfile/dropfile.scss index 8a4be8a31ad7..ed4c8e264f84 100644 --- a/src/dropfile/dropfile.scss +++ b/src/dropfile/dropfile.scss @@ -21,6 +21,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import '~gmf/sass/vars_only.scss'; + $bgselector-image-size: 3rem; .gmf-file-alert-contained { position: relative; diff --git a/src/dropfile/module.js b/src/dropfile/module.js index b52cd1b1f32f..0c7a1552dddf 100644 --- a/src/dropfile/module.js +++ b/src/dropfile/module.js @@ -21,7 +21,6 @@ import angular from 'angular'; import gmfFileDropZone from 'gmf/dropfile/component'; -import './dropfile.scss'; /** * @type {angular.IModule} diff --git a/src/editing/attributesComponent.js b/src/editing/attributesComponent.js index fd85537a403c..0167bf83f2fc 100644 --- a/src/editing/attributesComponent.js +++ b/src/editing/attributesComponent.js @@ -26,7 +26,6 @@ import {listen} from 'ol/events'; import ngeoMiscEventHelper from 'ngeo/misc/EventHelper'; import ngeoMiscDatetimepickerComponent from 'ngeo/misc/datetimepickerComponent'; import {ObjectEvent} from 'ol/Object'; -import './editing.css'; import htmlTemplate from './attributescomponent.html'; /** diff --git a/src/editing/editFeatureComponent.js b/src/editing/editFeatureComponent.js index 4a2541fe822d..03651d2be4e2 100644 --- a/src/editing/editFeatureComponent.js +++ b/src/editing/editFeatureComponent.js @@ -41,7 +41,6 @@ import gmfEditingXSDAttributes from 'gmf/editing/XSDAttributes'; import {getLayer as syncLayertreeMapGetLayer} from 'gmf/layertree/SyncLayertreeMap'; import DateFormatter from 'ngeo/misc/php-date-formatter'; import 'jquery-datetimepicker/jquery.datetimepicker'; -import 'jquery-datetimepicker/jquery.datetimepicker.css'; import ngeoEditingAttributesComponent from 'ngeo/editing/attributesComponent'; import ngeoEditingCreatefeatureComponent from 'ngeo/editing/createfeatureComponent'; import {deleteCondition} from 'ngeo/utils'; diff --git a/src/filter/component.js b/src/filter/component.js index 26513634603b..bccf558d9f7b 100644 --- a/src/filter/component.js +++ b/src/filter/component.js @@ -28,7 +28,6 @@ import ngeoFormatAttributeType from 'ngeo/format/AttributeType'; import ngeoRuleGeometry from 'ngeo/rule/Geometry'; import {getUid as olUtilGetUid} from 'ol/util'; import {remove as removeFromArray} from 'ol/array'; -import 'ngeo/sass/font.scss'; import panels from 'gmfapi/store/panels'; import htmlTemplate from './component.html'; /** diff --git a/src/filter/ruleComponent.js b/src/filter/ruleComponent.js index 4e40885380d6..aca926bd6d14 100644 --- a/src/filter/ruleComponent.js +++ b/src/filter/ruleComponent.js @@ -43,8 +43,8 @@ import olStyleText from 'ol/style/Text'; import olStyleFill from 'ol/style/Fill'; import {CollectionEvent} from 'ol/Collection'; import Feature from 'ol/Feature'; -import 'ngeo/sass/font.scss'; import htmlTemplate from './rulecomponent.html'; + /** * @typedef {Object} MenuEventTarget * @property {string} action diff --git a/src/floor/floor.scss b/src/floor/floor.scss index 3679831315f4..7d26e4f229dc 100644 --- a/src/floor/floor.scss +++ b/src/floor/floor.scss @@ -21,6 +21,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import '~gmf/sass/vars_only.scss'; + gmf-floorselector.gmf-floorselector { overflow: hidden; background-color: transparent; diff --git a/src/floor/module.js b/src/floor/module.js index 5b620074100f..3768b9c95516 100644 --- a/src/floor/module.js +++ b/src/floor/module.js @@ -22,8 +22,6 @@ import angular from 'angular'; import gmfFloorFloorSelectorComponent from 'gmf/floor/floorselectorComponent'; -import './floor.scss'; - /** * @type {!angular.IModule} */ diff --git a/src/grid/component.js b/src/grid/component.js index 1733d182f83c..922c4830105e 100644 --- a/src/grid/component.js +++ b/src/grid/component.js @@ -26,8 +26,8 @@ import ngeoMiscFilters from 'ngeo/misc/filters'; import {getRowUid} from 'ngeo/grid/Config'; import 'floatthead'; import 'angular-float-thead'; -import 'ngeo/sass/font.scss'; import htmlTemplate from './component.html'; + /** * @type {angular.IModule} * @hidden diff --git a/src/import/module.js b/src/import/module.js index 05eda31f46bb..19b763cbb958 100644 --- a/src/import/module.js +++ b/src/import/module.js @@ -24,8 +24,6 @@ import gmfImportImportdatasourceComponent from 'gmf/import/importdatasourceCompo import gmfImportWmsCapabilityLayertreeComponent from 'gmf/import/wmsCapabilityLayertreeComponent'; import gmfImportWmtsCapabilityLayertreeComponent from 'gmf/import/wmtsCapabilityLayertreeComponent'; -import './import.scss'; - /** * @type {angular.IModule} */ diff --git a/src/layertree/common.scss b/src/layertree/common.scss index bc6487dbdda0..19c913f65680 100644 --- a/src/layertree/common.scss +++ b/src/layertree/common.scss @@ -21,6 +21,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import '~gmf/sass/vars_only.scss'; +@import '@fortawesome/fontawesome-free/scss/variables.scss'; + .gmf-layertree-root-tools { text-align: right; padding: $micro-app-margin; diff --git a/src/layertree/module.js b/src/layertree/module.js index 1dffd061f607..12035a0e0bb8 100644 --- a/src/layertree/module.js +++ b/src/layertree/module.js @@ -27,12 +27,11 @@ import gmfLayertreeSyncLayertreeMap from 'gmf/layertree/SyncLayertreeMap'; import gmfLayertreeTimeSliderComponent from 'gmf/layertree/timeSliderComponent'; import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager'; -import './common.scss'; - /** * Also related to the map but not included in the module: * - ngeo.layertree.Controller (already required by ngeo.layertree.component) - * + * ./common.scss + * ./timeslider.scss * @type {angular.IModule} */ export default angular.module('ngeoLayertreeModule', [ diff --git a/src/layertree/timeSliderComponent.js b/src/layertree/timeSliderComponent.js index a84793568283..e2ccb638971e 100644 --- a/src/layertree/timeSliderComponent.js +++ b/src/layertree/timeSliderComponent.js @@ -24,9 +24,7 @@ import angular from 'angular'; import ngeoMiscWMSTime from 'ngeo/misc/WMSTime'; import ngeoMiscDebounce from 'ngeo/misc/debounce'; import 'jquery-ui/ui/widgets/slider'; -import 'ngeo/sass/jquery-ui.scss'; import 'angular-ui-slider'; -import './timeslider.scss'; import htmlTemplate from './timesliderComponent.html'; /** diff --git a/src/layertree/timeslider.scss b/src/layertree/timeslider.scss index e773ef82a646..a8c631000100 100644 --- a/src/layertree/timeslider.scss +++ b/src/layertree/timeslider.scss @@ -33,9 +33,9 @@ } .ui-slider-handle { - top: -(($gmf-input-range-thumb-height / 2) - $gmf-input-range-track-height / 2); + top: calc(($gmf-input-range-thumb-height * -1) / 2 - $gmf-input-range-track-height / 2); cursor: $gmf-input-range-cursor; - margin-left: -$gmf-input-range-thumb-width / 2; + margin-left: calc(($gmf-input-range-thumb-width * -1) / 2); box-shadow: $gmf-input-range-thumb-box-shadow; border: $gmf-input-range-thumb-border; height: $gmf-input-range-thumb-height; diff --git a/src/message/Disclaimer.js b/src/message/Disclaimer.js index 7a8cb2b1a6d0..ca76ef91deb2 100644 --- a/src/message/Disclaimer.js +++ b/src/message/Disclaimer.js @@ -23,7 +23,6 @@ import angular from 'angular'; import 'bootstrap/js/src/alert'; import ngeoMessagePopup, {MessagePopup} from 'ngeo/message/Popup'; import ngeoMessageMessage, {MessageType} from 'ngeo/message/Message_OLD'; // TODO: Use new ts file when convert done -import 'ngeo/sass/font.scss'; /** * A message to display by the disclaimer service. diff --git a/src/message/displaywindowComponent.js b/src/message/displaywindowComponent.js index 419f6acb63ce..5404206a6360 100644 --- a/src/message/displaywindowComponent.js +++ b/src/message/displaywindowComponent.js @@ -20,10 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import angular from 'angular'; -import 'ngeo/sass/font.scss'; import 'jquery-ui/ui/widgets/resizable'; import 'jquery-ui/ui/widgets/draggable'; -import 'ngeo/sass/jquery-ui.scss'; import 'angular-sanitize'; import htmlTemplate from './displaywindowComponent.html'; diff --git a/src/message/modalComponent.js b/src/message/modalComponent.js index 4d384c61e04d..fc3c570e56d1 100644 --- a/src/message/modalComponent.js +++ b/src/message/modalComponent.js @@ -21,7 +21,6 @@ import angular from 'angular'; import 'jquery-ui/ui/widgets/draggable'; -import 'ngeo/sass/jquery-ui.scss'; import 'bootstrap/js/src/modal'; /** diff --git a/src/misc/datepickerComponent.js b/src/misc/datepickerComponent.js index 7c8c7f8ea60d..a51f3394de1e 100644 --- a/src/misc/datepickerComponent.js +++ b/src/misc/datepickerComponent.js @@ -24,7 +24,6 @@ datePickerComponent.$inject = ['ngeoDatePickerTemplateUrl', '$timeout']; import angular from 'angular'; import ngeoMiscTime from 'ngeo/misc/Time'; import 'angular-ui-date'; -import 'ngeo/sass/jquery-ui.scss'; import htmlTemplate from './datepickerComponent.html'; // FIXME: import the locales in the applications diff --git a/src/misc/datetimepickerComponent.js b/src/misc/datetimepickerComponent.js index aaf0448b4dcc..4b1603b9edee 100644 --- a/src/misc/datetimepickerComponent.js +++ b/src/misc/datetimepickerComponent.js @@ -23,7 +23,6 @@ Controller.$inject = ['$element', 'gettextCatalog']; import angular from 'angular'; import DateFormatter from 'ngeo/misc/php-date-formatter'; import 'jquery-datetimepicker/jquery.datetimepicker'; -import 'jquery-datetimepicker/jquery.datetimepicker.css'; /** * @type {angular.IModule} diff --git a/src/misc/sortableComponent.js b/src/misc/sortableComponent.js index 2442ebc12867..ce7d55694368 100644 --- a/src/misc/sortableComponent.js +++ b/src/misc/sortableComponent.js @@ -22,7 +22,6 @@ sortableComponent.$inject = ['$timeout']; import angular from 'angular'; import 'jquery-ui/ui/widgets/sortable'; -import 'ngeo/sass/jquery-ui.scss'; import 'jquery-ui-touch-punch'; /** diff --git a/src/permalink/module.js b/src/permalink/module.js index 3d399411445e..9b30e7fb0a99 100644 --- a/src/permalink/module.js +++ b/src/permalink/module.js @@ -24,8 +24,6 @@ import gmfPermalinkPermalink from 'gmf/permalink/Permalink'; import gmfPermalinkShareService from 'gmf/permalink/ShareService'; import gmfPermalinkShareComponent from 'gmf/permalink/shareComponent'; -import './share.scss'; - /** * @type {angular.IModule} */ diff --git a/src/permalink/share.scss b/src/permalink/share.scss index 1e83cc3457f7..8029715deb67 100644 --- a/src/permalink/share.scss +++ b/src/permalink/share.scss @@ -21,6 +21,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import '~gmf/sass/vars.scss'; + gmf-share { .modal-body { textarea { diff --git a/src/print/module.js b/src/print/module.js index bacaf77324f2..04129c35e783 100644 --- a/src/print/module.js +++ b/src/print/module.js @@ -24,8 +24,6 @@ import ngeoPrintService from 'ngeo/print/Service'; import ngeoPrintUtils from 'ngeo/print/Utils'; import gmfPrintComponent from 'gmf/print/component'; -import './print.scss'; - /** * @type {angular.IModule} */ diff --git a/src/profile/module.js b/src/profile/module.js index 3cfa8a9a2664..c80871be908d 100644 --- a/src/profile/module.js +++ b/src/profile/module.js @@ -24,8 +24,6 @@ import ngeoProfileElevationComponent from 'ngeo/profile/elevationComponent'; import gmfProfileComponent from 'gmf/profile/component'; import gmfProfileDrawLineComponent from 'gmf/profile/drawLineComponent'; -import './profile.scss'; - /** * @type {angular.IModule} */ diff --git a/src/profile/profile.scss b/src/profile/profile.scss index cc5606cd609a..5118ce43ed6f 100644 --- a/src/profile/profile.scss +++ b/src/profile/profile.scss @@ -21,6 +21,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +@import '~gmf/sass/vars_only.scss'; + $profile-height: 12.5rem; .panel.gmf-profile-container { position: relative; diff --git a/src/query/extraModule.js b/src/query/extraModule.js index 8b971479bfe1..e6517d87322e 100644 --- a/src/query/extraModule.js +++ b/src/query/extraModule.js @@ -23,9 +23,6 @@ import angular from 'angular'; import gmfQueryGridComponent from 'gmf/query/gridComponent'; import gmfQueryWindowComponent from 'gmf/query/windowComponent'; -import './grid.scss'; -import './window.scss'; - /** * @type {angular.IModule} */ diff --git a/src/query/window.scss b/src/query/window.scss index c288515780f1..2977b34259d1 100644 --- a/src/query/window.scss +++ b/src/query/window.scss @@ -23,10 +23,10 @@ @import '~gmf/sass/vars.scss'; -$displayquerywindow-tablet-width: 9 * $map-tools-size; +$displayquerywindow-tablet-width: calc(9 * $map-tools-size); $displayquerywindow-detailed-header-height: 3.12rem; $displayquerywindow-detailed-details-line-height: 1.25rem; -$displayquerywindow-detailed-details-height: 9 * $displayquerywindow-detailed-details-line-height; +$displayquerywindow-detailed-details-height: calc(9 * $displayquerywindow-detailed-details-line-height); div.gmf-displayquerywindow { pointer-events: none; @@ -53,7 +53,7 @@ div.ngeo-displaywindow { left: initial; bottom: $app-margin; width: $displayquerywindow-tablet-width; - margin-left: -$displayquerywindow-tablet-width / 2; + margin-left: calc(($displayquerywindow-tablet-width * -1) / 2); position: fixed; z-index: $above-all; .collapse-button { @@ -66,7 +66,7 @@ div.ngeo-displaywindow { border-radius: $border-radius-base $border-radius-base 0 0; line-height: 0.5; height: $map-tools-size; - width: $map-tools-size + $map-tools-size * 2/3; + width: calc($map-tools-size + $map-tools-size * 2 / 3); } .collapse-button-up::after { content: fa-content($fa-var-chevron-up); @@ -250,7 +250,7 @@ div.ngeo-displaywindow { .animation-container { height: $map-tools-size * 2; &.animation-container-detailed { - height: ( + height: calc( $displayquerywindow-detailed-header-height + $displayquerywindow-detailed-details-height / 2 + $app-margin * 3 ) + $map-tools-size; diff --git a/src/query/windowComponent.js b/src/query/windowComponent.js index c9af3ab76b68..b36a59bca892 100644 --- a/src/query/windowComponent.js +++ b/src/query/windowComponent.js @@ -37,7 +37,6 @@ import olCollection from 'ol/Collection'; import {isEmpty} from 'ol/obj'; import {buildStyle} from 'ngeo/options'; import 'jquery-ui/ui/widgets/resizable'; -import 'ngeo/sass/jquery-ui.scss'; import 'angular-animate'; import 'angular-touch'; import 'bootstrap/js/src/collapse'; diff --git a/src/routing/RoutingComponent.js b/src/routing/RoutingComponent.js index 8d95910ba0cf..6d6113925ab0 100644 --- a/src/routing/RoutingComponent.js +++ b/src/routing/RoutingComponent.js @@ -35,7 +35,6 @@ import olStyleStroke from 'ol/style/Stroke'; import {toLonLat} from 'ol/proj'; import olFeature from 'ol/Feature'; import olGeomLineString from 'ol/geom/LineString'; -import 'ngeo/sass/font.scss'; import htmlTemplate from './routing.html'; /** diff --git a/src/routing/RoutingFeatureComponent.js b/src/routing/RoutingFeatureComponent.js index 5d6f9b3a77c6..8d87cb1c14f5 100644 --- a/src/routing/RoutingFeatureComponent.js +++ b/src/routing/RoutingFeatureComponent.js @@ -34,7 +34,6 @@ import olStyleStroke from 'ol/style/Stroke'; import olGeomPoint from 'ol/geom/Point'; import olInteractionModify from 'ol/interaction/Modify'; import olInteractionDraw from 'ol/interaction/Draw'; -import 'ngeo/sass/font.scss'; import htmlTemplate from './routingfeature.html'; /** diff --git a/src/routing/module.js b/src/routing/module.js index 953c0ee33fde..c066dbf78957 100644 --- a/src/routing/module.js +++ b/src/routing/module.js @@ -22,8 +22,6 @@ import angular from 'angular'; import ngeoRoutingRoutingComponent from 'ngeo/routing/RoutingComponent'; -import './routing.scss'; - /** * @type {angular.IModule} */ diff --git a/src/sass/base.scss b/src/sass/base.scss index 3195ff71d60c..0e57c4d8ff14 100644 --- a/src/sass/base.scss +++ b/src/sass/base.scss @@ -1,7 +1,7 @@ /** * The MIT License (MIT) * - * Copyright (c) 2022 Camptocamp SA + * Copyright (c) 2022-2024 Camptocamp SA * * 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 @@ -24,9 +24,7 @@ /** * Styles shared between the different apps (mobile and desktop). */ -@import '~ol/ol.css'; -@import '~gmf/css/reset.css'; -@import '~bootstrap/scss/bootstrap.scss'; +@import 'gmf/sass/vars_only.scss'; html, body { diff --git a/src/sass/components.scss b/src/sass/components.scss new file mode 100644 index 000000000000..f8a43188c97f --- /dev/null +++ b/src/sass/components.scss @@ -0,0 +1,16 @@ +@import 'ngeo/routing/routing.scss'; +@import 'ngeo/floor/floor.scss'; +@import 'ngeo/layertree/common.scss'; +@import 'ngeo/layertree/timeslider.scss'; +@import 'ngeo/profile/profile.scss'; +@import 'ngeo/search/search.scss'; +@import 'ngeo/permalink/share.scss'; +@import 'ngeo/import/import.scss'; +@import 'ngeo/contextualdata/contextualdata.scss'; +@import 'ngeo/dropfile/dropfile.scss'; +@import 'ngeo/print/print.scss'; +@import 'ngeo/query/grid.scss'; +@import 'ngeo/query/window.scss'; +@import 'ngeo/editing/editing.css'; +@import 'ngeo/sass/jquery-ui.scss'; +@import '~jquery-datetimepicker/jquery.datetimepicker.css'; diff --git a/src/sass/font.scss b/src/sass/font.scss index 7bcd1f96877b..db5f72f93e90 100644 --- a/src/sass/font.scss +++ b/src/sass/font.scss @@ -21,29 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/** - * The MIT License (MIT) - * - * Copyright (c) Camptocamp SA - * - * 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. -*/ - +$fa-font-path: '~@fortawesome/fontawesome-free/webfonts'; @import '~@fortawesome/fontawesome-free/scss/fontawesome.scss'; @import '~@fortawesome/fontawesome-free/scss/regular.scss'; @import '~@fortawesome/fontawesome-free/scss/solid.scss'; diff --git a/src/sass/fullscreenpopup.scss b/src/sass/fullscreenpopup.scss index fde12ef8b85e..444fe47e5a16 100644 --- a/src/sass/fullscreenpopup.scss +++ b/src/sass/fullscreenpopup.scss @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -@import '~gmf/sass/vars.scss'; +@import 'gmf/sass/vars.scss'; [ngeo-popup] { &.popover { diff --git a/src/sass/gmf-font.scss b/src/sass/gmf-font.scss index 6749dbdbab15..2652c37ed0b7 100644 --- a/src/sass/gmf-font.scss +++ b/src/sass/gmf-font.scss @@ -1,2 +1,2 @@ -@import '~gmf/sass/vars.scss'; -@import '~ngeo/sass/font.scss'; +@import 'gmf/sass/vars.scss'; +@import 'ngeo/sass/font.scss'; diff --git a/src/sass/map.scss b/src/sass/map.scss index 22ade8cd2860..9853abdb2b24 100644 --- a/src/sass/map.scss +++ b/src/sass/map.scss @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -@import '~gmf/sass/vars.scss'; +@import 'gmf/sass/vars.scss'; /** * Styles for the map and OL3 controls. @@ -119,7 +119,7 @@ button[ngeo-geolocation] { &::before { // same as fa-fw - width: (18em / 14); + width: calc(18em / 14); content: ''; text-align: center; } @@ -146,7 +146,7 @@ button[ngeo-geolocation] { span.gmf-backgroundlayerselector-opacity-check { &::after { - width: (18em / 14); + width: calc(18em / 14); font-family: 'Font Awesome 5 Free'; font-weight: 900; content: fa-content($fa-var-check); diff --git a/src/sass/popover.scss b/src/sass/popover.scss index 725ed74a195b..02b862d9e67c 100644 --- a/src/sass/popover.scss +++ b/src/sass/popover.scss @@ -21,12 +21,12 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -@import '~gmf/sass/vars.scss'; +@import 'gmf/sass/vars.scss'; $popover-nb-col: 12; -$popover-icon-max-width: ($popover-max-width / $popover-nb-col) * 3; -$popover-action-name-max-width: ($popover-max-width / $popover-nb-col) * 5; -$popover-action-max-width: ($popover-max-width / $popover-nb-col) * 4; +$popover-icon-max-width: calc(($popover-max-width / $popover-nb-col) * 3); +$popover-action-name-max-width: calc(($popover-max-width / $popover-nb-col) * 5); +$popover-action-max-width: calc(($popover-max-width / $popover-nb-col) * 4); .popover { border-radius: 0; diff --git a/src/sass/typeahead.scss b/src/sass/typeahead.scss index 90ed60185890..1bcbcce2c7ee 100644 --- a/src/sass/typeahead.scss +++ b/src/sass/typeahead.scss @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -@import '~gmf/sass/vars.scss'; +@import 'gmf/sass/vars.scss'; .twitter-typeahead { width: 100%; diff --git a/src/sass/vars.scss b/src/sass/vars.scss index 1fdf22f08d92..17f5c02ba638 100644 --- a/src/sass/vars.scss +++ b/src/sass/vars.scss @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -@import '~gmf/sass/vars_only.scss'; +@import 'gmf/sass/vars_only.scss'; @import '~bootstrap/scss/_functions.scss'; @import '~bootstrap/scss/_variables.scss'; diff --git a/src/sass/vars_only.scss b/src/sass/vars_only.scss index f676114b5749..c4825f4ac678 100644 --- a/src/sass/vars_only.scss +++ b/src/sass/vars_only.scss @@ -42,10 +42,10 @@ $map-tools-color: black !default; $onhover-color: darken($nav-bg, $standard-variation) !default; $onhover-color-darken: darken($onhover-color, $standard-variation) !default; $main-bg-color: #e2e3df !default; // gray light -$main-bg-color-lighten: lighten($main-bg-color, $standard-variation / 2) !default; +$main-bg-color-lighten: lighten($main-bg-color, calc($standard-variation / 2)) !default; $main-bg-color-09: rgba($main-bg-color, 0.9) !default; $main-bg-color-08: rgba($main-bg-color, 0.8) !default; -$search-width: 6 * $map-tools-size !default; +$search-width: calc(6 * $map-tools-size) !default; $border-radius-base: 0 !default; $nav-width: 20rem !default; $input-border-focus: darken($brand-primary, $standard-variation) !default; diff --git a/src/search/module.js b/src/search/module.js index 5da86422fac9..116abd445123 100644 --- a/src/search/module.js +++ b/src/search/module.js @@ -26,8 +26,6 @@ import ngeoSearchCreateLocationSearchBloodhound from 'ngeo/search/createLocation import gmfSearchComponent from 'gmf/search/component'; import gmfSearchFulltextSearch from 'gmf/search/FulltextSearch'; -import './search.scss'; - /** * @type {angular.IModule} */ diff --git a/src/search/search.scss b/src/search/search.scss index fbc344b4dd55..eadc99a1acf1 100644 --- a/src/search/search.scss +++ b/src/search/search.scss @@ -21,8 +21,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -@import '~gmf/sass/vars.scss'; -@import '~gmf/sass/typeahead.scss'; +@import 'gmf/sass/vars.scss'; +@import 'gmf/sass/typeahead.scss'; gmf-search { top: $app-margin; @@ -56,7 +56,7 @@ gmf-search { animation: spin 2.5s infinite linear; background-size: 20px; background-repeat: no-repeat; - background-image: url('../icons/spinner.svg'); + background-image: url('ngeo/icons/spinner.svg'); } } } @@ -130,11 +130,11 @@ gmf-search { .twitter-typeahead { .tt-menu { max-height: 75vh; + border-top: none; .gmf-search-no-results { padding: $app-margin; cursor: default; } - border-top: none; .gmf-search-header { padding: $app-margin; display: block; diff --git a/src/spinner/module.js b/src/spinner/module.js index e6eea7bd859c..5ddce43d342b 100644 --- a/src/spinner/module.js +++ b/src/spinner/module.js @@ -22,8 +22,6 @@ import angular from 'angular'; import gmfSpinnerDirective from 'gmf/spinner/directive'; -import './loader.scss'; - const myModule = angular.module('gmfSpinnerModule', [gmfSpinnerDirective.name]); /** diff --git a/src/streetview/MapillaryService.js b/src/streetview/MapillaryService.js index b8c7f73876c2..8592932afbac 100644 --- a/src/streetview/MapillaryService.js +++ b/src/streetview/MapillaryService.js @@ -19,7 +19,6 @@ // 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. import {StreetviewService} from './Service'; -import 'mapillary-js/dist/mapillary.css'; import {buffer} from 'ol/extent'; const MLY_METADATA_ENDPOINT = 'https://graph.mapillary.com'; From df7016846b4334d39a38d1684e585c382e8a2e10 Mon Sep 17 00:00:00 2001 From: Benjamin Gerber Date: Mon, 2 Sep 2024 09:25:58 +0200 Subject: [PATCH 2/2] Fix not working measure example --- examples/measure-ref.png | Bin 86008 -> 86090 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/measure-ref.png b/examples/measure-ref.png index a226030217b8b8528e7f50dcf9b1c77882dc8242..f71d2adce3d2b6f49edae4229f9e0da751a0c32f 100644 GIT binary patch delta 33972 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 delta 33901 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 i=W@(