diff --git a/CHANGELOG.md b/CHANGELOG.md index 200d7ba7..a02dcb17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +# Versão [1.2.0] + +## Genéricas + +- Documentação e ajustes no [Sistema de Privilégios](docs/servers.md) +- Implementação de opção para visualização do log do repositório + +## Implementação da API generatePPO + +- Foi implementada a API generatePPO que gera o conteúdo do PPO do arquivo em edição. Maiores detalhes em [API exportadas](https://github.com/totvs/tds-vscode/blob/dev/docs/exported-api.md) + +## Chave de compilação Inválida [Issue 563](https://github.com/totvs/tds-vscode/issues/563) + +### Problema: + +- Ao aplicar uma chave de compilação ocorre erro indicando que a chave é inválida. + +### Solução: + +- Foi aplicada uma correção interna nas validações da chave de compilação. + +## Implementação chamado #269 + +- Opção de manter as configurações de servidores na área de trabalho e [troca rápida](docs/servers.md) + +## Correção chamado #553 + +- Erro de compilação [FATAL] não é exibido na aba PROBLEMS e nem no LOG do AppServer. + # Versão [1.1.1] ## Correção chamado #549 diff --git a/docs/exported-api.md b/docs/exported-api.md new file mode 100644 index 00000000..6ba1229e --- /dev/null +++ b/docs/exported-api.md @@ -0,0 +1,26 @@ +# API exportadas + +Ao instalar a extensão tds-vscode é possível acessar as suas seguintes APIs exportadas. + +Clique na API para mais detalhes. + +
+ + generatePPO(filePath: string, options?: any): Promise<string> + + +
+Obtém o arquivo PPO correspondente referente ao arquivo informado. + +| Parâmetro | Descrição | +| --------- | --------- | +| filePath: string | Caminho completo do arquivo a ser processado. | +| options?: any | encoding com o qual o retorno deve ser codificado. Se omitido, o padrão cp1252 será utilizado. | + +| Retorno | Descrição | +| --------- | --------- | +| Promise<string> | Conteúdo do PPO gerado. | + +* O PPO será gerado com as mesmas características do arquivo compilado. +* Um servidor deve estar conectado para que o PPO seja gerado. +
diff --git a/docs/servers.md b/docs/servers.md index d5b71497..7590edff 100644 --- a/docs/servers.md +++ b/docs/servers.md @@ -1,7 +1,7 @@ # Visão `Servers` > Requisitos: -> - servidor a ser utilizado em execução +> - servidor a ser utilizado ou registrado em execução ## Registro de servidores @@ -22,3 +22,68 @@ - A conexão com servidores pode ser efetuada pela seleção do texto `[Selecionar servidor/ambiente]` na barra de ferramentas. Ou pelo atalho `CTRL + SHIFT + P` digite `TOTVS: Select Server`. ![Connect Server](./gifs/ConnectServer.gif) + +## Configurações das definições + +As configurações com os registros dos servidores podem ser editados manualmente, desde que com cuidado, via editor de texto. + +Pode-se acessá-lo acionando o ícone semelhante a uma engrenagem. + +![Edit file server](./gifs/serversEditFile.gif) + +## Local de gravação + +Por padrão, o arquivo com os registros de servidores é armazenado no arquivo `servers.json`, na área do usuário conforme o sistema operacional. + +* **Windows** `%USERPROFILE%\\.totvsls\\settings.json` +* **MacOS** `$HOME/.totvsls/settings.json` +* **Linux** `$HOME/.totvsls/settings.json` + +Caso deseje ter o registro de servidores por área de trabalho, ative a opção em `File | Preferences | Settings | Extensions | TOTVS | Workspace server config`. + +![Workspace Server Config](./images/workspaceServerConfig.png) + +Ou use a troca rápida disponível na barra de _status_. + +![Workspace Server Config](./gifs/toggleWorkspaceConfig.gif) + +> A troca rápida aplica-se somente a área de trabalho corrente e se sobrepoem a configuração padrão ou por usuário. Detalhes em [User and Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings). + +## Sistema de Privilégios + +O **TDS-VSCode**, suporta um sistema simples de privilégios, baseada em configuração efetuada no arquivo _appServer.ini_, podendo-se configurar privilégios para determinadas operações e estações, através da adição de chaves na sessão `[TDS]`. + +> Para manter o mesmo comportamento de ambientes com versões mais antigas, todas as operações vem liberadas por padrão, na ausência da sessão `[TDS]` ou da chave da operação. + +### Especificação da sessão + +``` +[TDS] +ALLOWAPPLYPATCH= +ALLOWEDIT= +ENABLEDISCONNECTUSER= +ENABLESENDMESSAGE= +ENABLEBLOCKNEWCONNECTION= +ENABLESTOPSERVER= +ALLOWBUILDPATCH= +ALLOWMONITOR= +ALLOWCOMPILE= +``` + +Chave | Permissão | +----- | --------- | +ALLOWAPPLYPATCH | Aplicar pacotes de atualização (_patchs_) +ALLOWEDIT | Editar configurações do _appServer_ +ENABLEDISCONNECTUSER | Desconectar usuários +ENABLESENDMESSAGE | Enviar mensagens +ENABLEBLOCKNEWCONNECTION | Bloquear novas conexões +ENABLESTOPSERVER | Encerrar o _appServer_ +ALLOWBUILDPATCH | Gerar pacotes de atualização (_patchs_) +ALLOWMONITOR | Monitorar conexões/sessões do _appServer_ +ALLOWCOMPILE | Compilar fontes e recursos +| + +- `Chave` deve ser sempre em maiúsculas +- `` é a lista de estações com o privilégio liberado, identificadas pelo seu endereço IP e separadas por `,`. + +> Para liberar o privilégio a qualquer estação, omita a chave ou coloque `*`. diff --git a/i18n/ptb/package.i18n.json b/i18n/ptb/package.i18n.json index 5c444fd9..1bd39b2b 100644 --- a/i18n/ptb/package.i18n.json +++ b/i18n/ptb/package.i18n.json @@ -13,6 +13,7 @@ "tds.package.show.ask.compile.result": "Pedir para exibir tabela com resultados da compilação", "tds.package.clear.console.before.compile": "Limpar o console antes da compilação", "tds.package.show.console.on.compile": "Exibir console na compilação", + "tds.package.show.banner": "Apresenta banner na inicialização", "tds.package.reconnectLastServer": "Reconectar ao último servidor conectado na inicialização.", "tds.package.generate.ppo": "Gere arquivo PPO.", "tds.package.show.precompile": "Mostrar comando pré compilador.", @@ -115,5 +116,6 @@ "tds-monitor.open-monitor-view": "Abrir exibição do monitor", "tds.package.workspaceServerConfig": "Use a área de trabalho para manter as configurações do servidor.", "tds.package.OpenTimeLineWebview": "Abrir visão da linha de tempo", - "tds.package.apply.formatting": "Aplica a formatação aos arquivos fontes TOTVS e suas variações." + "tds.package.apply.formatting": "Aplica a formatação aos arquivos fontes TOTVS e suas variações.", + "tds-monitor.open-rpoinfo": "Log de Repositório" } \ No newline at end of file diff --git a/i18n/rus/package.i18n.json b/i18n/rus/package.i18n.json index a2c2d6d5..2e51b177 100644 --- a/i18n/rus/package.i18n.json +++ b/i18n/rus/package.i18n.json @@ -5,115 +5,115 @@ // Do not edit this file. It is machine generated. { "tds.package.description": "TOTVS Developer Studio для VSCode", - "tds.package.args.for.lsp": "Массив, содержащий дополнительные аргументы для передачи в двоичный файл TOTVS Language Server", + "tds.package.args.for.lsp": "Массив с дополнительными аргументами для включения в двоичный файл TOTVS Language Server", "tds.package.max.problems.server": "Контролирует максимальное количество проблем, создаваемых сервером.", - "tds.package.trace.vscode.server": "Отслеживает связь между VS Code и языковым сервером.", - "tds.package.show.welcome.first.initialize": "Показать страницу приветствия при первой инициализации", - "tds.package.show.ask.encoding": "Запросить изменение кодировки для Windows-1252", - "tds.package.show.ask.compile.result": "Попросите показать таблицу с результатами компиляции", + "tds.package.trace.vscode.server": "Отслеживает обмен данными между VS Code и языковым сервером.", + "tds.package.show.welcome.first.initialize": "Показывать страницу приветствия при первом запуске", + "tds.package.show.ask.encoding": "Запросить изменение кодировки на Windows-1252", + "tds.package.show.ask.compile.result": "Запросить отображение таблицы с результатами компиляции", "tds.package.clear.console.before.compile": "Очистить консоль перед компиляцией", - "tds.package.show.console.on.compile": "Показать консоль при компиляции", - "tds.package.reconnectLastServer": "Повторно подключите последний подключенный сервер при запуске.", - "tds.package.generate.ppo": "Создать файл PPO.", - "tds.package.show.precompile": "Показать предварительную команду компилятора.", - "tds.package.compilation.includes": "Сборник включает в себя.", + "tds.package.show.console.on.compile": "Отображать консоль после компиляции", + "tds.package.reconnectLastServer": "Повторно подключиться при запуске к последнему подключенному серверу.", + "tds.package.generate.ppo": "Сгенерировать файл PPO.", + "tds.package.show.precompile": "Показать команду предварительной компиляции.", + "tds.package.compilation.includes": "Компиляция включает.", "tds.package.web.navigator.debug": "Веб-навигатор (отладка с помощью SmartClientHtml).", - "tds.package.editor.notification.show": "Уровень уведомлений будет отображаться во всплывающем окне.", - "tds.package.editor.notification.show.none": "Никто", + "tds.package.editor.notification.show": "Уровень уведомления будет отображаться во всплывающем окне", + "tds.package.editor.notification.show.none": "Нет", "tds.package.editor.notification.show.only_errors": "Только ошибки", "tds.package.editor.notification.show.errors_and_warnings": "Ошибки и предупреждения", - "tds.package.editor.notification.show.errors_warnings_and_infos": "Предупреждения об ошибках и информация", + "tds.package.editor.notification.show.errors_warnings_and_infos": "Ошибки, предупреждения и информация", "tds.package.editor.notification.show.all": "Все", - "tds.package.inspector.patch.title": "Информация о патче", - "tds.package.patchInfos.fromFile": "Информация о патче", - "tds.package.patchValidate.fromFile": "Подтверждение патча", - "tds.package.inspector.function.title": "Функции инспектора", - "tds.package.inspector.function.description": "Функции инспектора", + "tds.package.inspector.patch.title": "Информация о пакетах исправлений", + "tds.package.patchInfos.fromFile": "Информация о пакетах исправлений", + "tds.package.patchValidate.fromFile": "Проверка пакетов исправлений", + "tds.package.inspector.function.title": "Инспектор функций", + "tds.package.inspector.function.description": "Инспектор функций", "tds.package.inspector.object.title": "Инспектор объектов", "tds.package.inspector.object.description": "Инспектор объектов", "tds.package.defrag.rpo.title": "Дефрагментировать RPO", - "tds.package.defrag.rpo.description": "Дефрагментировать текущее RPO", - "tds.package.rpo.check.integrity.title": "RPO проверка целостности", - "tds.package.rpo.check.integrity.description": "Проверьте текущую целостность RPO", - "tds.package.build.file.title": "Компилировать файл/папку", - "tds.package.build.file.description": "Скомпилируйте файл/папку на серверах TOTVS", - "tds.package.rebuild.file.title": "Перекомпилировать файл/папку", - "tds.package.rebuild.file.description": "Перекомпилируйте файл/папку на серверах TOTVS", + "tds.package.defrag.rpo.description": "Дефрагментировать текущий RPO", + "tds.package.rpo.check.integrity.title": "Проверить целостность RPO", + "tds.package.rpo.check.integrity.description": "Проверить целостность текущего RPO", + "tds.package.build.file.title": "Компилировать файл / папку", + "tds.package.build.file.description": "Компилировать файл / папку в TOTVS Servers", + "tds.package.rebuild.file.title": "Перекомпилировать файл / папку", + "tds.package.rebuild.file.description": "Перекомпилировать файл / папку в TOTVS Servers", "tds.package.build.workspace.title": "Компилировать все рабочее пространство", - "tds.package.build.workspace.description": "Скомпилируйте текущее рабочее пространство.", + "tds.package.build.workspace.description": "Компилировать текущее рабочее пространство.", "tds.package.rebuild.workspace.title": "Перекомпилировать все рабочее пространство", - "tds.package.rebuild.workspace.description": "Перекомпилируйте текущее рабочее пространство.", + "tds.package.rebuild.workspace.description": "Перекомпилировать текущее рабочее пространство.", "tds.package.build.openEditors.title": "Компилировать открытые редакторы", - "tds.package.build.openEditors.description": "Скомпилируйте файлы из всех открытых редакторов", + "tds.package.build.openEditors.description": "Компилировать файлы из всех открытых редакторов", "tds.package.rebuild.openEditors.title": "Перекомпилировать открытые редакторы", - "tds.package.rebuild.openEditors.description": "Перекомпилируйте файлы из всех открытых редакторов", - "tds.package.delete.file.fromRPO.title": "Удалить файл/ресурс из RPO", - "tds.package.delete.file.fromRPO.description": "Удалить файл или ресурс из текущего RPO", - "tds.package.configure.launcher.title": "Настроить пусковые установки", - "tds.package.configure.launcher.description": "Страница, чтобы помочь на запуске конфигурации.", - "tds.package.getProgramName.title": "Спросите название программы", - "tds.package.getProgramName.description": "Спросите название программы.", - "tds.package.connect": "Cоединять", - "tds.package.reconnect": "Переустановка", - "tds.package.serverSelection": "Выберите сервер", - "tds.package.rename": "Nереименовать", - "tds.package.disconnect": "Отключить", - "tds.package.selectenv": "Выбрать", - "tds.package.freshenIndex": "Свежий индекс", + "tds.package.rebuild.openEditors.description": "Перекомпилировать файлы из всех открытых редакторов", + "tds.package.delete.file.fromRPO.title": "Удалить файл / ресурс из RPO", + "tds.package.delete.file.fromRPO.description": "Удалить файл / ресурс из текущего RPO", + "tds.package.configure.launcher.title": "Настроить средства запуска", + "tds.package.configure.launcher.description": "Страница справки по настройкам запуска.", + "tds.package.getProgramName.title": "Запросить имя программы", + "tds.package.getProgramName.description": "Запросить имя программы.", + "tds.package.connect": "Подключить", + "tds.package.reconnect": "Переподключить", + "tds.package.serverSelection": "Выбрать сервер", + "tds.package.rename": "Переименовать", + "tds.package.disconnect": "Отключить соединение", + "tds.package.selectenv": "Выбор", + "tds.package.freshenIndex": "Обновить индекс", "tds.package.add": "Добавить сервер", - "tds.package.config": "Настроить представление сервера", + "tds.package.config": "Настроить представление серверов", "tds.package.delete": "Удалить сервер", - "tds.package.patchGenerate.fromRPO": "Генерация патчей (от RPO)", - "tds.package.patchGenerate.fromFolder": "Генерация патчей (из папки)", - "tds.package.compile.key": "Ключ компиляции", - "tds.package.permissions.selectAction": "Выберите Действие", - "tds.package.logger.on": "На захвате регистратора", - "tds.package.logger.off": "Захват с регистратора", - "tds.package.patchApply": "Патч применить", - "tds.package.patchApply.fromFile": "Патч Применить из файла", + "tds.package.patchGenerate.fromRPO": "Генерация пакета исправлений (из RPO)", + "tds.package.patchGenerate.fromFolder": "Генерация пакета исправлений (из папки)", + "tds.package.compile.key": "Компилировать ключ", + "tds.package.permissions.selectAction": "Выбрать действие", + "tds.package.logger.on": "Включить средство захвата журналов", + "tds.package.logger.off": "Отключить средство захвата журналов", + "tds.package.patchApply": "Применить пакет исправлений", + "tds.package.patchApply.fromFile": "Применить пакет исправлений из файла", "tds.package.welcomePage": "Страница приветствия", - "tds.package.include": "Включают", - "tds.package.ws.show": "Генерация WS Protheus", - "tds.package.totvs_language_debug": "TOTVS Language Debug", - "tds.package.properties.program.description": "Название программы/функции", - "tds.package.properties.trace.description": "Включить ведение журнала протокола отладочного адаптера.", + "tds.package.include": "Включ.", + "tds.package.ws.show": "Генерировать WS Protheus", + "tds.package.totvs_language_debug": "Отладка TOTVS Language", + "tds.package.properties.program.description": "Имя программы / функции", + "tds.package.properties.trace.description": "Включить ведение журнала для протокола адаптера отладки.", "tds.package.properties.smartclientBin.description": "Полный путь к исполняемому файлу SmartClient.", - "tds.package.properties.cwb.description": "Корневой путь рабочей области", - "tds.package.properties.enableMultiThread.description": "Если отладка должна включать многопоточное выполнение", - "tds.package.properties.enableProfile.description": "Если профиль должен быть включен", - "tds.package.properties.isMultiSession.description": "Если это многосессионное выполнение (-M)", - "tds.package.properties.isAccessibilityMode.description": "Если режим доступности должен быть включен (-AC)", - "tds.package.properties.doNotShowSplash.description": "Если заставка не должна отображаться (-Q)", - "tds.package.properties.language.description": "Сообщает язык, чтобы начать выполнение (-L)", - "tds.package.properties.logFile.description": "DAP logfile только для устранения неполадок", - "tds.package.properties.ignoreFiles.description": "Заставьте отладчик игнорировать события останова в файлах, не найденных в WorkSpace", + "tds.package.properties.cwb.description": "Корневой путь к рабочему пространству", + "tds.package.properties.enableMultiThread.description": "Используется в случае, если отладка должна активировать многопоточное выполнение", + "tds.package.properties.enableProfile.description": "Используется для включения профиля", + "tds.package.properties.isMultiSession.description": "Используется при выполнении мультисессии (-M)", + "tds.package.properties.isAccessibilityMode.description": "Используется для включения режима доступности (-AC)", + "tds.package.properties.doNotShowSplash.description": "Используется для запрета отображения заставки (-Q)", + "tds.package.properties.language.description": "Сообщает языку о необходимости начала выполнения (-L)", + "tds.package.properties.logFile.description": "Файл журнала DAP только для устранения неполадок", + "tds.package.properties.ignoreFiles.description": "Команда отладчику игнорировать события прерываний в файлах, которые отсутствуют в WorkSpace", "tds.package.properties.toggleTableSync.description": "Включает или отключает синхронизацию таблиц с сервером", - "tds.package.totvs_language_debug.web": "Отладка языка TOTVS (SmartClient HTML)", + "tds.package.totvs_language_debug.web": "Веб-отладка TOTVS Language (SmartClient HTML)", "tds.package.server.view": "Серверы", - "tds.package.properties.program.description.web": "Название программы/функции", - "tds.package.properties.trace.description.web": "Включите ведение журнала протокола отладки.", - "tds.package.properties.smartclientUrl.description": "HTML-код SmartClient", - "tds.package.properties.workspaceFolders.description.web": "Пути в рабочей области", - "tds.package.properties.wsCacheFiles.description.web": "Включить/отключить начальный кеш файлов папок рабочего пространства (DAP)", + "tds.package.properties.program.description.web": "Имя программы / функции", + "tds.package.properties.trace.description.web": "Включить ведение журнала для протокола адаптера отладки.", + "tds.package.properties.smartclientUrl.description": "URL-адрес SmartClient HTML.", + "tds.package.properties.workspaceFolders.description.web": "Пути в рабочем пространстве", + "tds.package.properties.wsCacheFiles.description.web": "Включение / отключение начального кеширования файлов в папке рабочего пространства (DAP)", "tds.package.properties.webNavigator.description.web": "Веб-навигатор.", "tds.package.configurationSnippets.description": "Новая конфигурация для «отладки» выбранного пользователем файла AdvPL/4GL.", - "tds.package.configurationSnippets.description.web": "Новая конфигурация для «отладки» выбранного пользователем файла AdvPL/4GL с использованием SmartClient HTML.", - "tds.vscode.question.change.encoding": "Хотите изменить кодировку по умолчанию TOTVS (Windows-1252)?", - "tds.vscode.yes": "да", - "tds.vscode.no": "нет", - "tds.vscode.noAskAgain": "Не спрашивай снова", - "tds.toggle.autocomplete.behavior": "Переключить поведение автозаполнения", - "tds.package.editor.toggle.autocomplete": "Переключить поведение автозаполнения.", + "tds.package.configurationSnippets.description.web": "Новая конфигурация для «отладки» выбранного пользователем файла AdvPL/4GL с помощью SmartClient HTML.", + "tds.vscode.question.change.encoding": "Хотите изменить кодировку по умолчанию на TOTVS (Windows-1252)?", + "tds.vscode.yes": "Да", + "tds.vscode.no": "Нет", + "tds.vscode.noAskAgain": "Не спрашивать повторно", + "tds.toggle.autocomplete.behavior": "Переключить режим автозаполнения", + "tds.package.editor.toggle.autocomplete": "Переключить режим автозаполнения.", "tds.package.editor.toggle.autocomplete.basic": "Стандартная процедура VS Code.", - "tds.package.editor.toggle.autocomplete.ls": "Поиск на языковом сервере текущей среды.", - "tds.command.debug.toggleTableSync": "Переключить синхронизацию таблицы", - "tds.package.folder.enable.extensions.filter": "Компилировать только файлы с разрешенными расширениями.", - "tds.package.folder.extensions.allowed": "Разрешенные расширения для составления списка.", - "tds.package.tdsreplay.configure.launcher.title": "Воспроизведение TDS: настройка пусковых установок", - "tds.package.tdsreplay.configure.launcher.description": "Страница для помощи в настройках запуска воспроизведения TDS Replay.", - "tds.package.tdsreplay.debug": "Отладка воспроизведения TDS", - "tds-monitor.open-monitor-view": "Открыть монитор", - "tds.package.workspaceServerConfig": "Используйте рабочее пространство для поддержания настроек сервера.", - "tds.package.OpenTimeLineWebview": "Открыть TimeLine View", + "tds.package.editor.toggle.autocomplete.ls": "Поиск на языковом сервере в текущей среде.", + "tds.command.debug.toggleTableSync": "Переключить режим синхронизации таблиц", + "tds.package.folder.enable.extensions.filter": "Компилировать файлы только с разрешенными расширениями.", + "tds.package.folder.extensions.allowed": "Разрешенные расширения для списка компиляции.", + "tds.package.tdsreplay.configure.launcher.title": "TDS Replay: настройка средств запуска", + "tds.package.tdsreplay.configure.launcher.description": "Страница справки по настройкам запуска TDS Replay.", + "tds.package.tdsreplay.debug": "Отладка TDS Replay", + "tds-monitor.open-monitor-view": "Открыть просмотр монитора", + "tds.package.workspaceServerConfig": "Использовать рабочее пространство для сохранения настроек сервера.", + "tds.package.OpenTimeLineWebview": "Открыть веб-просмотр графика", "tds.package.apply.formatting": "Применяет форматирование к исходным файлам TOTVS и их вариантам." } \ No newline at end of file diff --git a/package.json b/package.json index e78e0773..eb93af0e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "tds-vscode", "displayName": "TOTVS Developer Studio for VSCode (AdvPL, TLPP e 4GL)", "description": "%tds.package.description%", - "version": "1.1.1", + "version": "1.2.0", "publisher": "TOTVS", "author": { "name": "TOTVS", @@ -63,8 +63,8 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.56", - "@totvs/tds-da": "^1.1.17", - "@totvs/tds-ls": "^1.1.33", + "@totvs/tds-da": "^1.1.19", + "@totvs/tds-ls": "^1.1.37", "@types/node": "^14.11.2", "@types/react": "^16.9.50", "@types/vscode": "^1.49.0", @@ -84,7 +84,9 @@ "typescript": "^4.0.3", "vscode-debugadapter": "^1.42.1", "vscode-languageclient": "^6.1.0", - "vscode-nls": "^5.0.0" + "vscode-nls": "^5.0.0", + "windows-1251": "^1.0.0", + "windows-1252": "^1.0.0" }, "devDependencies": { "@babel/cli": "^7.11.6", @@ -768,6 +770,15 @@ "light": "resources/light/monitor.png", "dark": "resources/dark/monitor.png" } + }, + { + "command": "tds-monitor.open-loadrpoinfo-view", + "title": "%tds-monitor.open-rpoinfo%", + "category": "TOTVSMonitor", + "icon": { + "light": "resources/light/rpolog.png", + "dark": "resources/dark/rpolog.png" + } } ], "keybindings": [ @@ -1290,6 +1301,11 @@ "when": "view == totvs_server && viewItem == serverItem", "group": "DtotvsInspect@2" }, + { + "command": "tds-monitor.open-loadrpoinfo-view", + "when": "view == totvs_server && viewItem == serverItem", + "group": "DtotvsInspect@3" + }, { "command": "totvs-developer-studio.selectenv", "when": "view == totvs_server && viewItem == envSectionNotCurrent", @@ -1436,4 +1452,4 @@ "servers": { "path": ".vscode/servers.json" } -} \ No newline at end of file +} diff --git a/package.nls.es.json b/package.nls.es.json index ae0a664d..f98936d2 100644 --- a/package.nls.es.json +++ b/package.nls.es.json @@ -111,5 +111,6 @@ "tds-monitor.open-monitor-view": "Vista de monitor abierta", "tds.package.workspaceServerConfig": "Use el espacio de trabajo para mantener la configuración del servidor.", "tds.package.OpenTimeLineWebview": "Abrir vista de línea de tiempo", - "tds.package.apply.formatting": "Aplica el formato a los archivos de origen TOTVS y sus variaciones." + "tds.package.apply.formatting": "Aplica el formato a los archivos de origen TOTVS y sus variaciones.", + "tds-monitor.open-rpoinfo": "Registro del repositorio" } \ No newline at end of file diff --git a/package.nls.json b/package.nls.json index 68870ae7..d5d6b7b6 100644 --- a/package.nls.json +++ b/package.nls.json @@ -111,5 +111,6 @@ "tds-monitor.open-monitor-view": "Open monitor view", "tds.package.workspaceServerConfig": "Use the workspace to maintain server settings.", "tds.package.OpenTimeLineWebview": "Open TimeLine Webview", - "tds.package.apply.formatting": "Applies formatting to TOTVS source files and their variations." + "tds.package.apply.formatting": "Applies formatting to TOTVS source files and their variations.", + "tds-monitor.open-rpoinfo": "Repository Log" } \ No newline at end of file diff --git a/package.nls.pt-br.json b/package.nls.pt-br.json index 08ec844e..68aa761a 100644 --- a/package.nls.pt-br.json +++ b/package.nls.pt-br.json @@ -8,7 +8,7 @@ "tds.package.show.ask.compile.result": "Pedir para exibir tabela com resultados da compilação", "tds.package.clear.console.before.compile": "Limpar o console antes da compilação", "tds.package.show.console.on.compile": "Exibir console na compilação", - "tds.package.show.banner": "Displays banner when starting", + "tds.package.show.banner": "Apresenta banner na inicialização", "tds.package.reconnectLastServer": "Reconectar ao último servidor conectado na inicialização.", "tds.package.generate.ppo": "Gere arquivo PPO.", "tds.package.show.precompile": "Mostrar comando pré compilador.", @@ -111,5 +111,6 @@ "tds-monitor.open-monitor-view": "Abrir exibição do monitor", "tds.package.workspaceServerConfig": "Use a área de trabalho para manter as configurações do servidor.", "tds.package.OpenTimeLineWebview": "Abrir visão da linha de tempo", - "tds.package.apply.formatting": "Aplica a formatação aos arquivos fontes TOTVS e suas variações." + "tds.package.apply.formatting": "Aplica a formatação aos arquivos fontes TOTVS e suas variações.", + "tds-monitor.open-rpoinfo": "Log de Repositório" } \ No newline at end of file diff --git a/package.nls.ru.json b/package.nls.ru.json index 56d983b7..a03752ea 100644 --- a/package.nls.ru.json +++ b/package.nls.ru.json @@ -1,115 +1,116 @@ { "tds.package.description": "TOTVS Developer Studio для VSCode", - "tds.package.args.for.lsp": "Массив, содержащий дополнительные аргументы для передачи в двоичный файл TOTVS Language Server", + "tds.package.args.for.lsp": "Массив с дополнительными аргументами для включения в двоичный файл TOTVS Language Server", "tds.package.max.problems.server": "Контролирует максимальное количество проблем, создаваемых сервером.", - "tds.package.trace.vscode.server": "Отслеживает связь между VS Code и языковым сервером.", - "tds.package.show.welcome.first.initialize": "Показать страницу приветствия при первой инициализации", - "tds.package.show.ask.encoding": "Запросить изменение кодировки для Windows-1252", - "tds.package.show.ask.compile.result": "Попросите показать таблицу с результатами компиляции", + "tds.package.trace.vscode.server": "Отслеживает обмен данными между VS Code и языковым сервером.", + "tds.package.show.welcome.first.initialize": "Показывать страницу приветствия при первом запуске", + "tds.package.show.ask.encoding": "Запросить изменение кодировки на Windows-1252", + "tds.package.show.ask.compile.result": "Запросить отображение таблицы с результатами компиляции", "tds.package.clear.console.before.compile": "Очистить консоль перед компиляцией", - "tds.package.show.console.on.compile": "Показать консоль при компиляции", + "tds.package.show.console.on.compile": "Отображать консоль после компиляции", "tds.package.show.banner": "Displays banner when starting", - "tds.package.reconnectLastServer": "Повторно подключите последний подключенный сервер при запуске.", - "tds.package.generate.ppo": "Создать файл PPO.", - "tds.package.show.precompile": "Показать предварительную команду компилятора.", - "tds.package.compilation.includes": "Сборник включает в себя.", + "tds.package.reconnectLastServer": "Повторно подключиться при запуске к последнему подключенному серверу.", + "tds.package.generate.ppo": "Сгенерировать файл PPO.", + "tds.package.show.precompile": "Показать команду предварительной компиляции.", + "tds.package.compilation.includes": "Компиляция включает.", "tds.package.web.navigator.debug": "Веб-навигатор (отладка с помощью SmartClientHtml).", - "tds.package.editor.notification.show": "Уровень уведомлений будет отображаться во всплывающем окне.", - "tds.package.editor.notification.show.none": "Никто", + "tds.package.editor.notification.show": "Уровень уведомления будет отображаться во всплывающем окне", + "tds.package.editor.notification.show.none": "Нет", "tds.package.editor.notification.show.only_errors": "Только ошибки", "tds.package.editor.notification.show.errors_and_warnings": "Ошибки и предупреждения", - "tds.package.editor.notification.show.errors_warnings_and_infos": "Предупреждения об ошибках и информация", + "tds.package.editor.notification.show.errors_warnings_and_infos": "Ошибки, предупреждения и информация", "tds.package.editor.notification.show.all": "Все", - "tds.package.inspector.patch.title": "Информация о патче", - "tds.package.patchInfos.fromFile": "Информация о патче", - "tds.package.patchValidate.fromFile": "Подтверждение патча", - "tds.package.inspector.function.title": "Функции инспектора", - "tds.package.inspector.function.description": "Функции инспектора", + "tds.package.inspector.patch.title": "Информация о пакетах исправлений", + "tds.package.patchInfos.fromFile": "Информация о пакетах исправлений", + "tds.package.patchValidate.fromFile": "Проверка пакетов исправлений", + "tds.package.inspector.function.title": "Инспектор функций", + "tds.package.inspector.function.description": "Инспектор функций", "tds.package.inspector.object.title": "Инспектор объектов", "tds.package.inspector.object.description": "Инспектор объектов", "tds.package.defrag.rpo.title": "Дефрагментировать RPO", - "tds.package.defrag.rpo.description": "Дефрагментировать текущее RPO", - "tds.package.rpo.check.integrity.title": "RPO проверка целостности", - "tds.package.rpo.check.integrity.description": "Проверьте текущую целостность RPO", - "tds.package.build.file.title": "Компилировать файл/папку", - "tds.package.build.file.description": "Скомпилируйте файл/папку на серверах TOTVS", - "tds.package.rebuild.file.title": "Перекомпилировать файл/папку", - "tds.package.rebuild.file.description": "Перекомпилируйте файл/папку на серверах TOTVS", + "tds.package.defrag.rpo.description": "Дефрагментировать текущий RPO", + "tds.package.rpo.check.integrity.title": "Проверить целостность RPO", + "tds.package.rpo.check.integrity.description": "Проверить целостность текущего RPO", + "tds.package.build.file.title": "Компилировать файл / папку", + "tds.package.build.file.description": "Компилировать файл / папку в TOTVS Servers", + "tds.package.rebuild.file.title": "Перекомпилировать файл / папку", + "tds.package.rebuild.file.description": "Перекомпилировать файл / папку в TOTVS Servers", "tds.package.build.workspace.title": "Компилировать все рабочее пространство", - "tds.package.build.workspace.description": "Скомпилируйте текущее рабочее пространство.", + "tds.package.build.workspace.description": "Компилировать текущее рабочее пространство.", "tds.package.rebuild.workspace.title": "Перекомпилировать все рабочее пространство", - "tds.package.rebuild.workspace.description": "Перекомпилируйте текущее рабочее пространство.", + "tds.package.rebuild.workspace.description": "Перекомпилировать текущее рабочее пространство.", "tds.package.build.openEditors.title": "Компилировать открытые редакторы", - "tds.package.build.openEditors.description": "Скомпилируйте файлы из всех открытых редакторов", + "tds.package.build.openEditors.description": "Компилировать файлы из всех открытых редакторов", "tds.package.rebuild.openEditors.title": "Перекомпилировать открытые редакторы", - "tds.package.rebuild.openEditors.description": "Перекомпилируйте файлы из всех открытых редакторов", - "tds.package.delete.file.fromRPO.title": "Удалить файл/ресурс из RPO", - "tds.package.delete.file.fromRPO.description": "Удалить файл или ресурс из текущего RPO", - "tds.package.configure.launcher.title": "Настроить пусковые установки", - "tds.package.configure.launcher.description": "Страница, чтобы помочь на запуске конфигурации.", - "tds.package.getProgramName.title": "Спросите название программы", - "tds.package.getProgramName.description": "Спросите название программы.", - "tds.package.connect": "Cоединять", - "tds.package.reconnect": "Переустановка", - "tds.package.serverSelection": "Выберите сервер", - "tds.package.rename": "Nереименовать", - "tds.package.disconnect": "Отключить", - "tds.package.selectenv": "Выбрать", - "tds.package.freshenIndex": "Свежий индекс", + "tds.package.rebuild.openEditors.description": "Перекомпилировать файлы из всех открытых редакторов", + "tds.package.delete.file.fromRPO.title": "Удалить файл / ресурс из RPO", + "tds.package.delete.file.fromRPO.description": "Удалить файл / ресурс из текущего RPO", + "tds.package.configure.launcher.title": "Настроить средства запуска", + "tds.package.configure.launcher.description": "Страница справки по настройкам запуска.", + "tds.package.getProgramName.title": "Запросить имя программы", + "tds.package.getProgramName.description": "Запросить имя программы.", + "tds.package.connect": "Подключить", + "tds.package.reconnect": "Переподключить", + "tds.package.serverSelection": "Выбрать сервер", + "tds.package.rename": "Переименовать", + "tds.package.disconnect": "Отключить соединение", + "tds.package.selectenv": "Выбор", + "tds.package.freshenIndex": "Обновить индекс", "tds.package.add": "Добавить сервер", - "tds.package.config": "Настроить представление сервера", + "tds.package.config": "Настроить представление серверов", "tds.package.delete": "Удалить сервер", - "tds.package.patchGenerate.fromRPO": "Генерация патчей (от RPO)", - "tds.package.patchGenerate.fromFolder": "Генерация патчей (из папки)", - "tds.package.compile.key": "Ключ компиляции", - "tds.package.permissions.selectAction": "Выберите Действие", - "tds.package.logger.on": "На захвате регистратора", - "tds.package.logger.off": "Захват с регистратора", - "tds.package.patchApply": "Патч применить", - "tds.package.patchApply.fromFile": "Патч Применить из файла", + "tds.package.patchGenerate.fromRPO": "Генерация пакета исправлений (из RPO)", + "tds.package.patchGenerate.fromFolder": "Генерация пакета исправлений (из папки)", + "tds.package.compile.key": "Компилировать ключ", + "tds.package.permissions.selectAction": "Выбрать действие", + "tds.package.logger.on": "Включить средство захвата журналов", + "tds.package.logger.off": "Отключить средство захвата журналов", + "tds.package.patchApply": "Применить пакет исправлений", + "tds.package.patchApply.fromFile": "Применить пакет исправлений из файла", "tds.package.welcomePage": "Страница приветствия", - "tds.package.include": "Включают", - "tds.package.ws.show": "Генерация WS Protheus", - "tds.package.totvs_language_debug": "TOTVS Language Debug", - "tds.package.properties.program.description": "Название программы/функции", - "tds.package.properties.trace.description": "Включить ведение журнала протокола отладочного адаптера.", + "tds.package.include": "Включ.", + "tds.package.ws.show": "Генерировать WS Protheus", + "tds.package.totvs_language_debug": "Отладка TOTVS Language", + "tds.package.properties.program.description": "Имя программы / функции", + "tds.package.properties.trace.description": "Включить ведение журнала для протокола адаптера отладки.", "tds.package.properties.smartclientBin.description": "Полный путь к исполняемому файлу SmartClient.", - "tds.package.properties.cwb.description": "Корневой путь рабочей области", - "tds.package.properties.enableMultiThread.description": "Если отладка должна включать многопоточное выполнение", - "tds.package.properties.enableProfile.description": "Если профиль должен быть включен", - "tds.package.properties.isMultiSession.description": "Если это многосессионное выполнение (-M)", - "tds.package.properties.isAccessibilityMode.description": "Если режим доступности должен быть включен (-AC)", - "tds.package.properties.doNotShowSplash.description": "Если заставка не должна отображаться (-Q)", - "tds.package.properties.language.description": "Сообщает язык, чтобы начать выполнение (-L)", - "tds.package.properties.logFile.description": "DAP logfile только для устранения неполадок", - "tds.package.properties.ignoreFiles.description": "Заставьте отладчик игнорировать события останова в файлах, не найденных в WorkSpace", + "tds.package.properties.cwb.description": "Корневой путь к рабочему пространству", + "tds.package.properties.enableMultiThread.description": "Используется в случае, если отладка должна активировать многопоточное выполнение", + "tds.package.properties.enableProfile.description": "Используется для включения профиля", + "tds.package.properties.isMultiSession.description": "Используется при выполнении мультисессии (-M)", + "tds.package.properties.isAccessibilityMode.description": "Используется для включения режима доступности (-AC)", + "tds.package.properties.doNotShowSplash.description": "Используется для запрета отображения заставки (-Q)", + "tds.package.properties.language.description": "Сообщает языку о необходимости начала выполнения (-L)", + "tds.package.properties.logFile.description": "Файл журнала DAP только для устранения неполадок", + "tds.package.properties.ignoreFiles.description": "Команда отладчику игнорировать события прерываний в файлах, которые отсутствуют в WorkSpace", "tds.package.properties.toggleTableSync.description": "Включает или отключает синхронизацию таблиц с сервером", - "tds.package.totvs_language_debug.web": "Отладка языка TOTVS (SmartClient HTML)", + "tds.package.totvs_language_debug.web": "Веб-отладка TOTVS Language (SmartClient HTML)", "tds.package.server.view": "Серверы", - "tds.package.properties.program.description.web": "Название программы/функции", - "tds.package.properties.trace.description.web": "Включите ведение журнала протокола отладки.", - "tds.package.properties.smartclientUrl.description": "HTML-код SmartClient", - "tds.package.properties.workspaceFolders.description.web": "Пути в рабочей области", - "tds.package.properties.wsCacheFiles.description.web": "Включить/отключить начальный кеш файлов папок рабочего пространства (DAP)", + "tds.package.properties.program.description.web": "Имя программы / функции", + "tds.package.properties.trace.description.web": "Включить ведение журнала для протокола адаптера отладки.", + "tds.package.properties.smartclientUrl.description": "URL-адрес SmartClient HTML.", + "tds.package.properties.workspaceFolders.description.web": "Пути в рабочем пространстве", + "tds.package.properties.wsCacheFiles.description.web": "Включение / отключение начального кеширования файлов в папке рабочего пространства (DAP)", "tds.package.properties.webNavigator.description.web": "Веб-навигатор.", "tds.package.configurationSnippets.description": "Новая конфигурация для «отладки» выбранного пользователем файла AdvPL/4GL.", - "tds.package.configurationSnippets.description.web": "Новая конфигурация для «отладки» выбранного пользователем файла AdvPL/4GL с использованием SmartClient HTML.", - "tds.vscode.question.change.encoding": "Хотите изменить кодировку по умолчанию TOTVS (Windows-1252)?", - "tds.vscode.yes": "да", - "tds.vscode.no": "нет", - "tds.vscode.noAskAgain": "Не спрашивай снова", - "tds.toggle.autocomplete.behavior": "Переключить поведение автозаполнения", - "tds.package.editor.toggle.autocomplete": "Переключить поведение автозаполнения.", + "tds.package.configurationSnippets.description.web": "Новая конфигурация для «отладки» выбранного пользователем файла AdvPL/4GL с помощью SmartClient HTML.", + "tds.vscode.question.change.encoding": "Хотите изменить кодировку по умолчанию на TOTVS (Windows-1252)?", + "tds.vscode.yes": "Да", + "tds.vscode.no": "Нет", + "tds.vscode.noAskAgain": "Не спрашивать повторно", + "tds.toggle.autocomplete.behavior": "Переключить режим автозаполнения", + "tds.package.editor.toggle.autocomplete": "Переключить режим автозаполнения.", "tds.package.editor.toggle.autocomplete.basic": "Стандартная процедура VS Code.", - "tds.package.editor.toggle.autocomplete.ls": "Поиск на языковом сервере текущей среды.", - "tds.command.debug.toggleTableSync": "Переключить синхронизацию таблицы", - "tds.package.folder.enable.extensions.filter": "Компилировать только файлы с разрешенными расширениями.", - "tds.package.folder.extensions.allowed": "Разрешенные расширения для составления списка.", - "tds.package.tdsreplay.configure.launcher.title": "Воспроизведение TDS: настройка пусковых установок", - "tds.package.tdsreplay.configure.launcher.description": "Страница для помощи в настройках запуска воспроизведения TDS Replay.", - "tds.package.tdsreplay.debug": "Отладка воспроизведения TDS", - "tds-monitor.open-monitor-view": "Открыть монитор", - "tds.package.workspaceServerConfig": "Используйте рабочее пространство для поддержания настроек сервера.", - "tds.package.OpenTimeLineWebview": "Открыть TimeLine View", - "tds.package.apply.formatting": "Применяет форматирование к исходным файлам TOTVS и их вариантам." + "tds.package.editor.toggle.autocomplete.ls": "Поиск на языковом сервере в текущей среде.", + "tds.command.debug.toggleTableSync": "Переключить режим синхронизации таблиц", + "tds.package.folder.enable.extensions.filter": "Компилировать файлы только с разрешенными расширениями.", + "tds.package.folder.extensions.allowed": "Разрешенные расширения для списка компиляции.", + "tds.package.tdsreplay.configure.launcher.title": "TDS Replay: настройка средств запуска", + "tds.package.tdsreplay.configure.launcher.description": "Страница справки по настройкам запуска TDS Replay.", + "tds.package.tdsreplay.debug": "Отладка TDS Replay", + "tds-monitor.open-monitor-view": "Открыть просмотр монитора", + "tds.package.workspaceServerConfig": "Использовать рабочее пространство для сохранения настроек сервера.", + "tds.package.OpenTimeLineWebview": "Открыть веб-просмотр графика", + "tds.package.apply.formatting": "Применяет форматирование к исходным файлам TOTVS и их вариантам.", + "tds-monitor.open-rpoinfo": "Repository Log" } \ No newline at end of file diff --git a/src/compile/tdsBuild.ts b/src/compile/tdsBuild.ts index dbca6394..72e6dd8b 100644 --- a/src/compile/tdsBuild.ts +++ b/src/compile/tdsBuild.ts @@ -5,6 +5,9 @@ import * as fs from 'fs'; import Utils from "../utils"; import { showCompileResult } from "./buildResult"; +var windows1252 = require('windows-1252'); +var windows1251 = require('windows-1251'); + import * as nls from "vscode-nls"; import { ResponseError } from "vscode-languageclient"; import { CompileResult } from "./compileResult"; @@ -18,6 +21,7 @@ interface CompileOptions { generatePpoFile: boolean; showPreCompiler: boolean; priorVelocity: boolean; + returnPpo: boolean; } //TODO: pegar as opções de compilação da configuração (talvez por server? ou workspace?) @@ -33,9 +37,106 @@ function _getCompileOptionsDefault(): CompileOptions { generatePpoFile: generatePpoFile as boolean, showPreCompiler: showPreCompiler as boolean, priorVelocity: true, + returnPpo: false }; } +export function generatePpo(filePath: string, options?: any): Promise { + return new Promise((resolve, reject) => { + if (!filePath || filePath.length == 0) { + reject(new Error("Undefined filePath.")); + return; + } + if (!fs.existsSync(filePath)) { + reject(new Error("File '" + filePath + "' not found.")); + return; + } + + const server = utils.getCurrentServer(); + if (!server) { + reject(new Error("No server connected. Check if there is a server connected in 'totvs.tds-vscode' extension.")); + return; + } + + const serverItem = utils.getServerForID(server.id); + let isAdvplsource: boolean = Utils.isAdvPlSource(filePath); + if (!isAdvplsource) { + reject(new Error("This file has an invalid AdvPL source file extension.")); + return; + } + + const includes = utils.getIncludes(true, serverItem) || []; + let includesUris: Array = includes.map((include) => { + return vscode.Uri.file(include).toString(); + }); + if (includesUris.length == 0) { + reject(new Error("Includes undefined.")); + return; + } + + let filesUris: Array = []; + filesUris.push(vscode.Uri.file(filePath).toString()); + + //const configADVPL = vscode.workspace.getConfiguration("totvsLanguageServer"); + let extensionsAllowed: string[]; + // if (configADVPL.get("folder.enableExtensionsFilter", true)) { + // extensionsAllowed = configADVPL.get("folder.extensionsAllowed", []); // Le a chave especifica + // } + + const permissionsInfos = Utils.getPermissionsInfos(); + + const compileOptions = _getCompileOptionsDefault(); + compileOptions.recompile = true; + compileOptions.generatePpoFile = false; + compileOptions.showPreCompiler = false; + compileOptions.returnPpo = true; + + sendCompilation(server, permissionsInfos, includesUris, filesUris, compileOptions, extensionsAllowed, isAdvplsource) + .then( + (response: CompileResult) => { + if (response.compileInfos.length > 0) { + for (let index = 0; index < response.compileInfos.length; index++) { + const compileInfo = response.compileInfos[index]; + if (compileInfo.status === "APPRE") { + // o compileInfo.detail chega do LS com encoding utf8 + // a extensão tds-vscode realiza a conversão para o enconding conforme informado em options.encoding + // caso nenhum encoding seja informado, converte para o padrão AdvPL cp1252 + if (options && options.encoding) { + let encoding: string = (options.encoding).toLowerCase(); + //console.log("encoding: "+encoding); + if (options.encoding === 'utf8') { + resolve(compileInfo.detail); + } + else if (encoding === 'windows-1252' || encoding === 'cp1252') { + //let apple = "Maçã"; + //console.log(apple); + resolve(windows1252.encode(compileInfo.detail)); + } + else if (encoding === 'windows-1251' || encoding === 'cp1251') { + //let helloWorld = "Привет мир"; + //console.log(helloWorld); + //resolve(windows1251.encode(helloWorld)); + resolve(windows1251.encode(compileInfo.detail)); + } + else { + // unknown encoding - fallback to utf8 + resolve(compileInfo.detail); + } + } + else { + // if there is no encoding option - use windows-1252 + resolve(windows1252.encode(compileInfo.detail)); + } + } + } + } + }, + (err: ResponseError) => { + reject(new Error(err.message)); + }); + }); +} + /** * Builds a file. */ @@ -104,7 +205,7 @@ async function buildCode( return; } } - + let includesUris: Array = []; for (let idx = 0; idx < includes.length; idx++) { includesUris.push(vscode.Uri.file(includes[idx]).toString()); diff --git a/src/compileKey/compileKey.ts b/src/compileKey/compileKey.ts index ee8219e4..e48e1536 100644 --- a/src/compileKey/compileKey.ts +++ b/src/compileKey/compileKey.ts @@ -19,12 +19,30 @@ const localizeHTML = { "tds.webview.compile.key.token": localize("tds.webview.compile.key.token", "Token"), "tds.webview.compile.key.overwrite": localize("tds.webview.compile.key.overwrite", "Allow overwrite default"), "tds.webview.compile.key.setting": localize("tds.webview.compile.key.setting", "These settings can also be changed in"), - "tds.webview.compile.key.validated": localize("tds.webview.compile.key.invalid", "Key successfully validated"), + "tds.webview.compile.key.validated": localize("tds.webview.compile.key.validated", "Key successfully validated"), "tds.webview.compile.key.invalid": localize("tds.webview.compile.key.invalid", "Invalid key"), }; -export function compileKeyPage(context: vscode.ExtensionContext) { +export interface CompileKey { + path: string; + machineId: string; + issued: string; + expire: string; + buildType: string; + tokenKey: string; + authorizationToken: string; + userId: string; +} +export interface Authorization { + id: string; + generation: string; + validation: string; + permission: string; + key: string; +} + +export function compileKeyPage(context: vscode.ExtensionContext) { if(!isLSInitialized) { languageClient.onReady().then(async () => { initializePage(context); @@ -61,7 +79,7 @@ export function compileKeyPage(context: vscode.ExtensionContext) { getId(currentPanel); const compileKey = Utils.getPermissionsInfos(); - if (compileKey !== "" && compileKey.authorizationToken && !compileKey.userId) { + if (compileKey && compileKey.authorizationToken) { // && !compileKey.userId) { const generated = compileKey.issued; const expiry = compileKey.expire; const canOverride: boolean = compileKey.buildType === "0"; @@ -69,6 +87,7 @@ export function compileKeyPage(context: vscode.ExtensionContext) { } currentPanel.webview.onDidReceiveMessage(message => { + console.log("onDidReceiveMessage: " + message.command); switch (message.command) { case 'saveKey': if (message.token) { @@ -79,17 +98,18 @@ export function compileKeyPage(context: vscode.ExtensionContext) { } break; case 'readFile': - const compileKey = Utils.readCompileKeyFile(message.path); - compileKey.path = message.path; - let canOverride: boolean = compileKey.permission === "1"; - setCurrentKey(currentPanel, compileKey.path, compileKey.id, compileKey.generation, compileKey.validation, compileKey.key, canOverride); - validateKey(currentPanel, { - 'id': compileKey.id.toUpperCase(), - 'generated': compileKey.generation, - 'expire': compileKey.validation, - 'overwrite': canOverride, - 'token': compileKey.key.toUpperCase() - }, false); + const authorization: Authorization = Utils.readCompileKeyFile(message.path); + if (authorization) { + let canOverride: boolean = authorization.permission === "1"; + setCurrentKey(currentPanel, message.path, authorization.id, authorization.generation, authorization.validation, authorization.key, canOverride); + validateKey(currentPanel, { + 'id': authorization.id.toUpperCase(), + 'generated': authorization.generation, + 'expire': authorization.validation, + 'overwrite': canOverride, + 'token': authorization.key.toUpperCase() + }, false); + } break; case 'validateKey': if (message.token) { @@ -99,13 +119,7 @@ export function compileKeyPage(context: vscode.ExtensionContext) { } break; case 'cleanKey': - const config = Utils.getServersConfig(); - if (config.permissions.authorizationToken) { - const infos = { - "authorizationToken": "" - }; - Utils.savePermissionsInfos(infos); - } + Utils.deletePermissionsInfos(); break; } }, @@ -142,10 +156,16 @@ function getId(currentPanel) { }); } +class ValidKeyResult { + authorizationToken: string; + buildType: number; +} + function validateKey(currentPanel, message, close: boolean) { + console.log("validateKey: " + message.token); if (message.token) { let canOverride = "0"; - if (message.overwrite === true) { + if (message.overwrite) { canOverride = "1"; } languageClient.sendRequest('$totvsserver/validKey', { @@ -156,24 +176,29 @@ function validateKey(currentPanel, message, close: boolean) { 'canOverride': canOverride, 'token': message.token } - }).then((response: any) => { - let outputMessageText; - let outputMessageType; - if (message.path) { - response.path = message.path; - } - if (response.buildType === 0 || response.buildType === 1 || response.buildType === 2) { - response.tokenKey = message.token; - response.machineId = message.id; - response.issued = message.generated; - response.expire = message.expire; - response.userId = ""; + }).then((response: ValidKeyResult) => { + console.log("validateKey response authorizationToken: " + response.authorizationToken); + let outputMessageText: string; + let outputMessageType: string; + if (response.authorizationToken !== "") { + console.log("validateKey success"); if (close) { - Utils.savePermissionsInfos(response); + let permission: CompileKey = { + path: message.path, + machineId: message.id, + issued: message.generated, + expire: message.expire, + buildType: String(response.buildType), + tokenKey: message.token, + authorizationToken: response.authorizationToken, + userId: "" + } + Utils.savePermissionsInfos(permission); } outputMessageText = localizeHTML["tds.webview.compile.key.validated"]; outputMessageType = "success"; } else { + console.log("validateKey error"); outputMessageText = localizeHTML["tds.webview.compile.key.invalid"]; outputMessageType = "error"; } @@ -205,26 +230,26 @@ function getWebViewContent(context: vscode.ExtensionContext, localizeHTML) { return runTemplate({ css: cssContent, localize: localizeHTML }); } -export function updatePermissionBarItem(infos: any | undefined): void { - if (infos.authorizationToken) { +export function updatePermissionBarItem(infos: CompileKey): void { + if (infos && infos.authorizationToken && infos.buildType && infos.expire) { const [dd, mm, yyyy] = infos.expire.split("/"); const expiryDate: Date = new Date(`${yyyy}-${mm}-${dd} 23:59:59`); if (expiryDate.getTime() >= new Date().getTime()) { const newLine = "\n"; permissionStatusBarItem.text = 'Permissions: Logged in'; if (infos.machineId) { - permissionStatusBarItem.tooltip = infos.machineId + newLine; + permissionStatusBarItem.tooltip = "Machine ID: " + infos.machineId + newLine; }else if(infos.userId){ - permissionStatusBarItem.tooltip = infos.userId + newLine; + permissionStatusBarItem.tooltip = "User ID: " + infos.userId + newLine; } permissionStatusBarItem.tooltip += "Expires in " + expiryDate.toLocaleString() + newLine; - if (infos.buildType === 0) { + if (infos.buildType === "0") { permissionStatusBarItem.tooltip += "Allow compile functions and overwrite default TOTVS"; - } else if (infos.buildType === 1) { + } else if (infos.buildType === "1") { permissionStatusBarItem.tooltip += "Allow only compile users functions"; - } else if (infos.buildType === 2) { + } else if (infos.buildType === "2") { permissionStatusBarItem.tooltip += "Allow compile functions"; } } else { diff --git a/src/extension.ts b/src/extension.ts index 453131df..4c268263 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -7,7 +7,7 @@ import * as nls from "vscode-nls"; const localize = nls.config({ locale: vscode.env.language, - bundleFormat: nls.BundleFormat.standalone + bundleFormat: nls.BundleFormat.standalone, })(); import * as ls from "vscode-languageserver-types"; @@ -36,6 +36,7 @@ import { commandBuildFile, commandBuildWorkspace, commandBuildOpenEditors, + generatePpo, } from "./compile/tdsBuild"; import { deleteFileFromRPO } from "./server/deleteFileFromRPO"; import { defragRpo } from "./server/defragRPO"; @@ -70,6 +71,7 @@ import { import { registerAdvplOutline, register4glOutline } from "./outline"; import { registerDebug, _debugEvent } from "./debug"; import { openMonitorView } from "./monitor/monitorLoader"; +import { openRpoInfoView } from "./rpoInfo/rpoInfoLoader"; export let languageClient: LanguageClient; // barra de status @@ -494,6 +496,17 @@ export function activate(context: ExtensionContext) { }) ); + //rpo log + context.subscriptions.push( + vscode.commands.registerCommand("tds-monitor.open-loadrpoinfo-view", () => { + vscode.window.setStatusBarMessage( + "Aguarde. Iniciando visualização...", + 5000 + ); + openRpoInfoView(context); + }) + ); + //Mostra a pagina de Welcome. showWelcomePage(context, false); //Abre uma caixa de informações para login no servidor protheus selecionado. @@ -596,6 +609,14 @@ export function activate(context: ExtensionContext) { //verifyEncoding(); showBanner(); + + let exportedApi = { + generatePPO(filePath: string, options?: any): Promise { + return generatePpo(filePath, options); + } + } + // 'export' public api-surface + return exportedApi; } function instanceOfUri(object: any): object is Uri { @@ -674,14 +695,26 @@ function showBanner(force: boolean = false) { if (showBanner || force) { let ext = vscode.extensions.getExtension("TOTVS.tds-vscode"); /* prettier-ignore-start */ - languageClient.outputChannel.appendLine("---------------------------v---------------------------------------------------"); - languageClient.outputChannel.appendLine(" ////// //// ////// | TOTVS Developer Studio for VS-Code"); - languageClient.outputChannel.appendLine(" // // // // | Version " + ext.packageJSON["version"]); - languageClient.outputChannel.appendLine(" // // // ////// | TOTVS Technology"); + languageClient.outputChannel.appendLine( + "---------------------------v---------------------------------------------------" + ); + languageClient.outputChannel.appendLine( + " ////// //// ////// | TOTVS Developer Studio for VS-Code" + ); + languageClient.outputChannel.appendLine( + " // // // // | Version " + ext.packageJSON["version"] + ); + languageClient.outputChannel.appendLine( + " // // // ////// | TOTVS Technology" + ); languageClient.outputChannel.appendLine(" // // // // |"); - languageClient.outputChannel.appendLine(" // //// ////// | https://github.com/totvs/tds-vscode"); - languageClient.outputChannel.appendLine(" --------------------------^---------------------------------------------------"); + languageClient.outputChannel.appendLine( + " // //// ////// | https://github.com/totvs/tds-vscode" + ); + languageClient.outputChannel.appendLine( + " --------------------------^---------------------------------------------------" + ); /* prettier-ignore-end */ } } -} \ No newline at end of file +} diff --git a/src/monitor/app/monitorPanel.tsx b/src/monitor/app/monitorPanel.tsx index 0be9111a..af9187ce 100644 --- a/src/monitor/app/monitorPanel.tsx +++ b/src/monitor/app/monitorPanel.tsx @@ -135,7 +135,6 @@ function buildColumns(memento: IMemento): [] { } try { - //para mascarar erro devido a erro na implemtação anterior const orderColumn: any = columnsOrder.find((column: any) => { return column.field === columns[index]["field"]; }); diff --git a/src/protocolMessages.ts b/src/protocolMessages.ts index 7d717f6d..7ecfd26e 100644 --- a/src/protocolMessages.ts +++ b/src/protocolMessages.ts @@ -19,6 +19,7 @@ import { languageClient } from "./extension"; import { ResponseError } from "vscode-languageclient"; import { ServerItem } from "./serverItemProvider"; import { CompileResult } from "./compile/compileResult"; +import { IRpoInfoData as RpoInfoResult } from "./rpoInfo/rpoPath"; export enum ConnTypeIds { CONNT_DEBUGGER = 3, @@ -66,7 +67,6 @@ class DisconnectReturnInfo { message: string; } - export function sendDisconnectRequest( connectedServerItem: ServerItem ): Thenable { @@ -152,8 +152,8 @@ export function sendConnectRequest( } export const ENABLE_CODE_PAGE = { - CP1252: 'CP1252', //demais idiomas - CP1251: 'CP1251' //cirílico + CP1252: "CP1252", //demais idiomas + CP1251: "CP1251", //cirílico }; export function sendAuthenticateRequest( @@ -161,7 +161,7 @@ export function sendAuthenticateRequest( environment: string, user: string, password: string, - encoding: string, + encoding: string ): Thenable { return languageClient .sendRequest("$totvsserver/authentication", { @@ -170,7 +170,7 @@ export function sendAuthenticateRequest( environment: environment, user: user, password: password, - encoding: encoding + encoding: encoding, }, }) .then( @@ -288,13 +288,12 @@ export function sendLockServer( }); } -export function sendIsLockServer( - server: ServerItem -): Thenable { +export function sendIsLockServer(server: ServerItem): Thenable { return languageClient .sendRequest("$totvsmonitor/getConnectionStatus", { getConnectionStatusInfo: { - connectionToken: server.token }, + connectionToken: server.token, + }, }) .then((response: any) => { return !response.status; //false: conexões bloqueadas @@ -357,8 +356,9 @@ export function sendUserMessage( server: target.server, environment: target.environment, message: message, - } - }).then( + }, + }) + .then( (response: any) => { return response.message; }, @@ -367,6 +367,7 @@ export function sendUserMessage( } ); } + export function sendAppKillConnection( server: ServerItem, target: any @@ -403,7 +404,7 @@ export function sendCompilation( return languageClient.sendRequest("$totvsserver/compilation", { compilationInfo: { connectionToken: server.token, - authorizationToken: permissionsInfos.authorizationToken, + authorizationToken: permissionsInfos ? permissionsInfos.authorizationToken : "", environment: server.environment, includeUris: includesUris, fileUris: filesUris, @@ -413,3 +414,18 @@ export function sendCompilation( }, }); } + +export function sendRpoInfo(server: ServerItem): Thenable { + return languageClient + .sendRequest("$totvsserver/rpoInfo", { + rpoInfo: { + connectionToken: server.token, + environment: server.environment, + }, + }) + .then( + (response: RpoInfoResult) => { + return response; + } + ); +} diff --git a/src/rpoInfo/actions.ts b/src/rpoInfo/actions.ts new file mode 100644 index 00000000..5e7ea19f --- /dev/null +++ b/src/rpoInfo/actions.ts @@ -0,0 +1,11 @@ +export interface IRpoInfoPanelAction { + action: RpoInfoPanelAction; + content: any; +} + +export enum RpoInfoPanelAction { + ExportToTxt, + ExportToJson, + UpdateRpoInfo, + DoUpdateState +} diff --git a/src/rpoInfo/app/index.tsx b/src/rpoInfo/app/index.tsx new file mode 100644 index 00000000..9b3f3146 --- /dev/null +++ b/src/rpoInfo/app/index.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import * as ReactDOM from "react-dom"; + +import RpoInfoPanel from "./rpoInfoPanel"; +import ErrorBoundary from "../helper/errorBoundary"; +import { i18n } from "../helper"; + +declare global { + interface Window { + acquireVsCodeApi(): any; + initialData: any; + } +} + +const vscode = window.acquireVsCodeApi(); +const translations = window.initialData.translations; +const memento = {}; + +i18n.translations = translations; + +ReactDOM.render( + + + , + document.getElementById("root") +); diff --git a/src/rpoInfo/app/rpoInfoInterface.tsx b/src/rpoInfo/app/rpoInfoInterface.tsx new file mode 100644 index 00000000..25944c93 --- /dev/null +++ b/src/rpoInfo/app/rpoInfoInterface.tsx @@ -0,0 +1,23 @@ + +export const cellDefaultStyle = { + cellStyle: { + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + maxWidth: "30em", + minWidth: "8em", + padding: "0px", + paddingLeft: "5px", + paddingRight: "5px", + }, + headerStyle: { + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + maxWidth: "30em", + minWidth: "8em", + padding: "0px", + paddingLeft: "5px", + paddingRight: "5px", + }, +}; diff --git a/src/rpoInfo/app/rpoInfoPanel.tsx b/src/rpoInfo/app/rpoInfoPanel.tsx new file mode 100644 index 00000000..6d26f23a --- /dev/null +++ b/src/rpoInfo/app/rpoInfoPanel.tsx @@ -0,0 +1,431 @@ +import * as React from "react"; +import MaterialTable, { MTableToolbar } from "material-table"; +import { + createStyles, + makeStyles, + Theme +} from "@material-ui/core/styles"; +import Paper from "@material-ui/core/Paper"; +import { rpoInfoIcons } from "../helper/rpoInfoIcons"; +import { IRpoInfoPanelAction, RpoInfoPanelAction } from "../actions"; +import FilterList from "@material-ui/icons/FilterList"; +import { cellDefaultStyle } from "./rpoInfoInterface"; +import { IMemento, useMemento } from "../helper/memento"; +import { + propPageSize, + DEFAULT_TABLE, + propColumnHidden, + propColumns, + propOrderBy, + propOrderDirection, + propColumnsOrder +} from "./rpoInfoPanelMemento"; +import { i18n } from "../helper"; +import RpoInfoTheme, { inputTextStyles, useToolbarStyles } from "../helper/theme"; +import { IRpoInfoData, IRpoPatch } from "../rpoPath"; +import { FilledInput, FormControl, Grid, Input, InputLabel, SvgIconProps, Typography } from "@material-ui/core"; +import TreeView from '@material-ui/lab/TreeView'; +import TreeItem, { TreeItemProps } from '@material-ui/lab/TreeItem'; +import TextField from '@material-ui/core/TextField'; +import Label from '@material-ui/icons/Label'; +import SaveAlt from "@material-ui/icons/SaveAlt"; + +interface RenderTree { + name: string; + children?: RenderTree[]; + rpoPatch?: IRpoPatch; +} + + +interface IRpoInfoPanel { + vscode: any; + memento: any; +} + +let listener = undefined; + +interface ITitleProps { + title: string; + subtitle: string; +} + +function Title(props: ITitleProps) { + const style = useToolbarStyles(); + + return ( + <> +
{props.title}
+
{props.subtitle}
+ + ); +} + +const useTreeItemStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + color: theme.palette.text.secondary, + '&:hover > $content': { + backgroundColor: theme.palette.action.hover, + }, + '&:focus > $content, &$selected > $content': { + backgroundColor: `var(--tree-view-bg-color, ${theme.palette.grey[400]})`, + color: 'var(--tree-view-color)', + }, + '&:focus > $content $label, &:hover > $content $label, &$selected > $content $label': { + backgroundColor: 'transparent', + }, + }, + content: { + color: theme.palette.text.secondary, + borderTopRightRadius: theme.spacing(2), + borderBottomRightRadius: theme.spacing(2), + paddingRight: theme.spacing(1), + fontWeight: theme.typography.fontWeightMedium, + '$expanded > &': { + fontWeight: theme.typography.fontWeightRegular, + }, + }, + group: { + marginLeft: 0, + '& $content': { + paddingLeft: theme.spacing(2), + }, + }, + expanded: {}, + selected: {}, + label: { + fontWeight: 'inherit', + color: 'inherit', + }, + labelRoot: { + display: 'flex', + alignItems: 'center', + padding: theme.spacing(0.5, 0), + }, + labelIcon: { + marginRight: theme.spacing(1), + }, + labelText: { + fontWeight: 'inherit', + flexGrow: 1, + }, + }), +); + +type StyledTreeItemProps = TreeItemProps & { + bgColor?: string; + color?: string; + labelIcon: React.ElementType; + labelInfo?: string; + labelText: string; +}; + +declare module 'csstype' { + interface Properties { + '--tree-view-color'?: string; + '--tree-view-bg-color'?: string; + } +} + +function StyledTreeItem(props: StyledTreeItemProps) { + const classes = useTreeItemStyles(); + const { labelText, labelIcon: LabelIcon, labelInfo, color, bgColor, ...other } = props; + + return ( + + + + {labelText} + + + {labelInfo} + + + } + classes={{ + root: classes.root, + content: classes.content, + expanded: classes.expanded, + selected: classes.selected, + group: classes.group, + label: classes.label, + }} + {...other} + /> + ); +} + +function buildColumns(memento: IMemento): [] { + let columns = propColumns({ ...cellDefaultStyle }).columns; + const orderBy = memento.get(propOrderBy()) || ""; + const defaultSort = + orderBy === -1 ? "" : memento.get(propOrderDirection()) || "asc"; + let columnsOrder: any[] = memento.get(propColumnsOrder()) || []; + + for (let index = 0; index < columns.length; index++) { + const value = memento.get(propColumnHidden(columns[index].field)); + + if (value !== undefined) { + columns[index]["hiddenByColumnsButton"] = value; + columns[index]["hidden"] = value; + } + + if (orderBy === columns[index]["field"]) { + columns[index]["defaultSort"] = defaultSort; + } + + try { + const orderColumn: any = columnsOrder.find((column: any) => { + return column.field === columns[index]["field"]; + }); + + if (orderColumn) { + columns[index]["columnOrder"] = orderColumn.columnOrder; + } + } catch (error) { + columnsOrder = []; + } + } + + if (columnsOrder.length > 0) { + columns = columns.sort(function (a: any, b: any): any { + return a.columnOrder - b.columnOrder; + }); + } + + return columns; +} + +let memento: IMemento = undefined; + +export default function RpoLogPanel(props: IRpoInfoPanel) { + memento = useMemento( + props.vscode, + "RPO_INFO_PANEL", + RpoInfoPanelAction.DoUpdateState, + DEFAULT_TABLE(), + props.memento + ); + + const [rows, setRows] = React.useState([]); + const [currentNode, setCurrentNode] = React.useState(); + const [data, setData] = React.useState(); + const [subtitle, setSubtitle] = React.useState(); + const [rpoInfo, setRpoInfo] = React.useState(null); + const [pageSize, setPageSize] = React.useState(memento.get(propPageSize())); + const [filtering, setFiltering] = React.useState(false); + const [columns] = React.useState(buildColumns(memento)); + + if (listener === undefined) { + listener = (event: MessageEvent) => { + const message = event.data; // The JSON data our extension sent + + switch (message.command) { + case RpoInfoPanelAction.UpdateRpoInfo: { + const rpoInfo: IRpoInfoData = message.data.rpoInfo as IRpoInfoData; + const nodes: RenderTree = { name: rpoInfo.environment, children: [] }; + + rpoInfo.rpoPatchs.forEach((rpoPatch: IRpoPatch) => { + const name = rpoPatch.dateFileApplication.split(" ")[0]; + if (!nodes.children.find((element: any) => element.name == name)) { + nodes.children.push({ name: name, rpoPatch: rpoPatch }) + } + }); + + setData(nodes); + setSubtitle(message.data.serverName); + setRpoInfo({ version: rpoInfo.rpoVersion, date: rpoInfo.dateGeneration, environment: rpoInfo.environment }); + break; + } + default: + console.log("***** ATTENTION: rpoInfoPanel.tsx"); + console.log("\tCommand not recognized: " + message.command); + break; + } + }; + + window.addEventListener("message", listener); + } + + const doOrderChange = (orderBy: number, direction: string) => { + const columns = propColumns().columns; + + memento.set(propOrderBy(columns[orderBy]["field"])); + memento.set(propOrderDirection(direction)); + }; + + const doChangeRowsPerPage = (value: number) => { + setPageSize(value); + memento.set(propPageSize(value)); + }; + + const actions = []; + + actions.push({ + icon: () => + filtering ? : , + tooltip: i18n.localize("FILTERING_ON_OFF", "Filtering on/off"), + isFreeAction: true, + onClick: () => { + setFiltering(!filtering); + }, + }); + + actions.push({ + icon: () => , + tooltip: i18n.localize("EXPORT", "Export as text file"), + isFreeAction: true, + onClick: () => { + let command: IRpoInfoPanelAction = { + action: RpoInfoPanelAction.ExportToTxt, + content: { + rpoInfo: rpoInfo, + rpoPath: currentNode + }, + }; + + props.vscode.postMessage(command); + }, + }); + + const hashCode = (s: string) => s.split('').reduce((a, b) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a }, 0) + + const doClickNode = (event: React.MouseEvent, name: string) => { + event.preventDefault(); + + const currentNode: RenderTree[] = data.children.filter((element: RenderTree) => element.name == name); + if (currentNode.length == 1) { + setRows(currentNode[0].rpoPatch.programsApp); + setCurrentNode(currentNode[0].rpoPatch); + } else { + setRows([]); + setCurrentNode(null); + } + } + + const renderTree = (nodes: RenderTree) => ( + doClickNode(event, nodes.name)} + > + {Array.isArray(nodes.children) ? nodes.children.map((node) => renderTree(node)) : null} + + ); + + const toolBarStyle = useToolbarStyles(); + const inputTextClasses = inputTextStyles(); + const rpo = rpoInfo || ({ version: "", date: "", environment: "" }); + + return ( + + + + + + + RPO + + + + + + } + > + {data && renderTree(data)} + + + + + + + ( +
+ + + <Grid container xs={12} > + <Grid item container xs> + <Grid item xs={12}> + <Typography variant="overline" gutterBottom>Generation</Typography> + </Grid> + <Grid item xs> + <TextField margin="dense" label="Date" variant="outlined" disabled size="small" value={currentNode && currentNode.dateFileGeneration} /> + </Grid> + <Grid item xs> + <TextField margin="dense" label="Build" variant="outlined" disabled size="small" value={currentNode && currentNode.buildFileGeneration} /> + </Grid> + </Grid> + + <Grid item container xs> + <Grid item xs={12}> + <Typography variant="overline" gutterBottom>Application</Typography> + </Grid> + <Grid item xs> + <TextField margin="dense" label="Date" variant="outlined" disabled size="small" value={currentNode && currentNode.dateFileApplication} /> + </Grid> + <Grid item xs> + <TextField margin="dense" label="Build" variant="outlined" disabled size="small" value={currentNode && currentNode.buildFileApplication} /> + </Grid> + </Grid> + + <Grid container item xs={12}> + <Typography hidden={!currentNode || !currentNode.skipOld} variant="h6" color="secondary">This file overwrote more recent resources.</Typography> + </Grid> + </Grid> + + <MTableToolbar {...props} /> + </div> + ), + }} + localization={i18n.materialTableLocalization} + icons={rpoInfoIcons.table} + columns={rows.length ? columns : []} + data={rows} + options={{ + searchFieldAlignment: "left", + searchFieldStyle: { marginLeft: "-16px" }, + showTextRowsSelected: false, + emptyRowsWhenPaging: false, + pageSize: pageSize, + pageSizeOptions: [10, 50, 100], + paginationType: "normal", + thirdSortClick: true, + selection: false, + grouping: false, + filtering: filtering, + exportButton: false, + padding: "dense", + actionsColumnIndex: 0, + columnsButton: false, + sorting: true, + showTitle: false, + toolbarButtonAlignment: "right", + }} + actions={actions} + onChangeRowsPerPage={(value) => doChangeRowsPerPage(value)} + onOrderChange={(orderBy, direction) => + doOrderChange(orderBy, direction) + } + /> + </Grid> + </Grid> + </Paper> + </RpoInfoTheme> + ); +} diff --git a/src/rpoInfo/app/rpoInfoPanelMemento.tsx b/src/rpoInfo/app/rpoInfoPanelMemento.tsx new file mode 100644 index 00000000..b93f0666 --- /dev/null +++ b/src/rpoInfo/app/rpoInfoPanelMemento.tsx @@ -0,0 +1,127 @@ +import { cellDefaultStyle } from "./rpoInfoInterface"; +import { i18n, mergeProperties } from "../helper"; + +function fieldDef( + field: string, + title: string, + extraProps: any = { hidden: false, ...cellDefaultStyle } +): any { + return { field: field, title: title, ...extraProps }; +} + +export const propPageSize = (value: number = undefined) => { + return { + props: { + options: { + pageSize: value, + }, + }, + }; +}; + +export const propFiltering = (value: boolean = undefined) => { + return { + props: { + options: { + filtering: value, + }, + }, + }; +}; + +export const getColumn = (name: string) => { + let result = undefined; + const columns = propColumns(); + + for (let index = 0; index < columns.length; index++) { + const element = columns[index]; + if (element.field === name) { + result = element; + break; + } + } + + return result; +}; + +export const propColumn = ( + name: string, + key: string, + value: any = undefined +): any => { + return { + customColumns: { + [name]: { [key]: value }, + }, + }; +}; + +export const propColumnHidden = ( + name: string, + value: boolean = undefined +): any => { + return propColumn(name, "hidden", value); +}; + +export const propColumnGroup = ( + name: string, + value: boolean = undefined +): any => { + return propColumn(name, "XXXX", value); +}; + +export const propOrderDirection = (value: string = undefined): any => { + return { + customProps: { + direction: value, + }, + }; +}; + +export const propOrderBy = (value: number = undefined): any => { + return { + customProps: { + orderBy: value, + }, + }; +}; + +export const propColumnsOrder = (value: any[] = undefined): any => { + return { + customProps: { + columnsOrder: value, + }, + }; +}; + +export const _propColumnList = (): any => { + return { + columns: [], + }; +}; + +export const propColumns = (extraProps?: any): any => { + const remarkProps = { + ...(extraProps || {}), + cellStyle: { + textOverflow: "ellipsis", + whiteSpace: "nowrap", + overflow: "hidden", + maxWidth: 300, + }, + }; + + return { + columns: [ + fieldDef("name", i18n.localize("PROGRAM", "Program"), extraProps), + fieldDef("date", i18n.localize("DATE", "Date"), extraProps), + ], + }; +}; + +export const DEFAULT_TABLE = () => + mergeProperties([ + propColumns({ ...cellDefaultStyle }), + propPageSize(10), + propFiltering(false), + ]); diff --git a/src/rpoInfo/app/tsconfig.json b/src/rpoInfo/app/tsconfig.json new file mode 100644 index 00000000..baa14679 --- /dev/null +++ b/src/rpoInfo/app/tsconfig.json @@ -0,0 +1,23 @@ + +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES6", + "moduleResolution": "node", + "outDir": "../../../out", + "lib": [ + "es6", + "dom" + ], + "jsx": "react", + "sourceMap": true, + "noUnusedLocals": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/src/rpoInfo/helper/errorBoundary.tsx b/src/rpoInfo/helper/errorBoundary.tsx new file mode 100644 index 00000000..f38de064 --- /dev/null +++ b/src/rpoInfo/helper/errorBoundary.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; + +export default class ErrorBoundary extends React.Component<any, any> { + constructor(props: any) { + super(props); + + this.state = { hasError: false, error: undefined }; + } + + static getDerivedStateFromError(error) { + // Update state so the next render will show the fallback UI. + return { hasError: true, error: error }; + } + + componentDidCatch(error, errorInfo) { + // You can also log the error to an error reporting service + console.log(error, errorInfo); + } + + render() { + if (this.state.hasError) { + return ( + <> + <h1>Something went wrong.</h1> + {this.state} + </> + ); + } + + return this.props.children; + } +} diff --git a/src/rpoInfo/helper/i18n.ts b/src/rpoInfo/helper/i18n.ts new file mode 100644 index 00000000..f87e14b9 --- /dev/null +++ b/src/rpoInfo/helper/i18n.ts @@ -0,0 +1,90 @@ +let _translations = {}; + +class I18n { + private _translations: any = {}; + + public get translations(): any { + return this._translations; + } + + public set translations(value: any) { + this._translations = value || {}; + } + + public localize( + key: string, + message: string, + ...args: (string | number | boolean | undefined | null)[] + ): string { + let result = message; + + if (this._translations.hasOwnProperty(key)) { + result = this._translations[key]; + } + + if (args && args.length > 0) { + args.forEach((arg: any, index: number) => { + result = result.replace( + "{" + index + "}", + "" + (args[index] || "null") + ); + }); + } + + return result; + } + + public get materialTableLocalization(): any { + return { + pagination: { + labelDisplayedRows: "{from}-{to}/{count}", + labelRowsSelect: this.localize("RESOURCES", "resources"), + labelRowsPerPage: this.localize("LINES_PAGE.", "lines/p."), + firstAriaLabel: this.localize("FIRST", "First"), + firstTooltip: this.localize("FIRST_PAGE", "First page"), + previousAriaLabel: this.localize("PREVIOUS", "Previous"), + previousTooltip: this.localize("PREVIOUS_PAGE", "Previous page"), + nextAriaLabel: this.localize("NEXT", "Next"), + nextTooltip: this.localize("NEXT_PAGE", "Next page"), + lastAriaLabel: this.localize("LAST", "Last"), + lastTooltip: this.localize("LAST_PAGE", "Last page"), + }, + toolbar: { + nRowsSelected: this.localize( + "CONNECTIONS_SELECTED", + "{0} connections selected" + ), + addRemoveColumns: this.localize( + "SHOW_HIDE_COLUMNS", + "Show/hide columns" + ), + searchTooltip: this.localize( + "SEARCH_ALL_COLUMNS", + "Search in all columns" + ), + searchPlaceholder: this.localize("SEARCH", "Search"), + showColumnsTitle: this.localize("SHOW_COLUMNS", "Show Columns"), + showColumnsAriaLabel: this.localize("SHOW_COLUMNS", "Show Columns"), + exportName: this.localize("EXPORT_TXT", "Export as Text") + }, + header: { + actions: this.localize("ACTIONS", "Actions"), + }, + body: { + emptyDataSourceMessage: this.localize( + "NO_INFO_FROM_RPO", + "There is no information about the RPO." + ), + filterRow: { + filterTooltip: this.localize("FILTER", "Filter"), + }, + }, + grouping: { + placeholder: this.localize("DRAG_HEADERS", "Drag headers ..."), + groupedBy: this.localize("GROUPED_BY", "Grouped by:"), + }, + }; + } +} + +export const i18n = new I18n(); diff --git a/src/rpoInfo/helper/index.ts b/src/rpoInfo/helper/index.ts new file mode 100644 index 00000000..b19fc4c5 --- /dev/null +++ b/src/rpoInfo/helper/index.ts @@ -0,0 +1,4 @@ +import { i18n } from "../../monitor/helper"; + +export { useMemento, mergeProperties, IMemento } from "./memento"; +export { i18n } from "./i18n"; diff --git a/src/rpoInfo/helper/memento.ts b/src/rpoInfo/helper/memento.ts new file mode 100644 index 00000000..c0ebba1a --- /dev/null +++ b/src/rpoInfo/helper/memento.ts @@ -0,0 +1,164 @@ +export interface IMemento { + get: (property: any) => any; + set: (property: any) => any; + save: (reset?: boolean) => void; + reload: () => void; +} + +function getValue(target: any, properties: any): any { + let result = undefined; + + for (const key in target) { + const element = target[key]; + + if (properties.hasOwnProperty(key)) { + if (Array.isArray(element)) { + let list = []; + + if (element.length > 0) { + for (let index = 0; index < element.length; index++) { + const item = element[index]; + const value = getValue(item, properties[key][index]); + if (value) { + list.push(value); + } + } + } else { + list = properties[key]; + } + + result = list; + } else if (typeof element === "object") { + result = getValue(element, properties[key]); + } else { + result = properties[key]; + } + } + + if (result) { + break; + } + } + + return result; +} + +export function mergeProperties(properties: any[]): any { + let result = {}; + + properties.forEach((element) => { + result = update(result, element); + }); + + return result; +} + +function update(target: any, properties: any): any { + for (const key in properties) { + const element = properties[key]; + + if (typeof element === "object") { + if (target.hasOwnProperty(key)) { + target[key] = update(target[key], properties[key]); + } else { + target[key] = element; + } + } else { + target[key] = element; + } + } + + return target; +} + +function doLoadProperty(state: any, property: any, defaultValue: any): any { + let value = getValue(property, state); + + if (value === undefined) { + value = getValue(property, defaultValue); + } + + return value; +} + +function doSaveProperty(state: any, propertySave: any): any { + return mergeProperties([state, propertySave]); +} + +function doSave( + vscode: any, + id: string, + notifyCommand: string, + state: any, + reset: boolean +) { + let command: any = { + action: notifyCommand, + content: { key: id, state: state, reload: reset }, + }; + + vscode.postMessage(command); +} + +const mementoList: any = {}; + +export function useMemento( + vscode: any, + id: string, + notifyCommand: any, + defaultValues: any, + initialValues: any = {}, + autoSave: boolean = true +): any { + if (mementoList.hasOwnProperty(id) && mementoList[id] !== undefined) { + return mementoList[id]; + } + + mementoList[id] = { + defaultValues: defaultValues, + state: initialValues, + get: (property: any): any => { + let state = mementoList[id]["state"]; + let defaultValues = mementoList[id]["defaultValues"]; + + return doLoadProperty(state, property, defaultValues); + }, + set: (property: any) => { + let state = mementoList[id]["state"]; + const oldState = JSON.stringify(state); + let savedState = doSaveProperty(state, property); + + if (oldState !== JSON.stringify(savedState)) { + state = { ...state, ...savedState }; + + mementoList[id]["state"] = state; + + if (autoSave) { + doSave(vscode, id, notifyCommand, state, false); + } + } + }, + save: (reset: boolean = false) => { + let state = mementoList[id]["state"]; + + if (reset) { + state = {}; + mementoList[id] = undefined; + } + + doSave(vscode, id, notifyCommand, state, reset); + }, + reload: () => { + let state = mementoList[id]["state"]; + + let command: any = { + action: notifyCommand, + content: { key: id, state: state, reload: true }, + }; + + vscode.postMessage(command); + }, + }; + + return mementoList[id]; +} diff --git a/src/rpoInfo/helper/rpoInfoIcons.tsx b/src/rpoInfo/helper/rpoInfoIcons.tsx new file mode 100644 index 00000000..90fae3d7 --- /dev/null +++ b/src/rpoInfo/helper/rpoInfoIcons.tsx @@ -0,0 +1,158 @@ +import * as React from "react"; +import AddBox from "@material-ui/icons/AddBox"; +import ArrowDownward from "@material-ui/icons/ArrowDownward"; +import Check from "@material-ui/icons/Check"; +import ChevronLeft from "@material-ui/icons/ChevronLeft"; +import ChevronRight from "@material-ui/icons/ChevronRight"; +import Clear from "@material-ui/icons/Clear"; +import Delete from "@material-ui/icons/Delete"; +import Edit from "@material-ui/icons/Edit"; +import FilterList from "@material-ui/icons/FilterList"; +import FirstPage from "@material-ui/icons/FirstPage"; +import LastPage from "@material-ui/icons/LastPage"; +import Remove from "@material-ui/icons/Remove"; +import SaveAlt from "@material-ui/icons/SaveAlt"; +import Search from "@material-ui/icons/Search"; +import ViewColumn from "@material-ui/icons/ViewColumn"; +import { SvgIcon, SvgIconProps } from "@material-ui/core"; +import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown"; +import ArrowRightIcon from "@material-ui/icons/ArrowRight"; + +function MinusSquare(props: SvgIconProps) { + return ( + <SvgIcon fontSize="inherit" style={{ width: 14, height: 14 }} {...props}> + {/* tslint:disable-next-line: max-line-length */} + <path d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 11.023h-11.826q-.375 0-.669.281t-.294.682v0q0 .401.294 .682t.669.281h11.826q.375 0 .669-.281t.294-.682v0q0-.401-.294-.682t-.669-.281z" /> + </SvgIcon> + ); +} + +function PlusSquare(props: SvgIconProps) { + return ( + <SvgIcon fontSize="inherit" style={{ width: 14, height: 14 }} {...props}> + {/* tslint:disable-next-line: max-line-length */} + <path d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 12.977h-4.923v4.896q0 .401-.281.682t-.682.281v0q-.375 0-.669-.281t-.294-.682v-4.896h-4.923q-.401 0-.682-.294t-.281-.669v0q0-.401.281-.682t.682-.281h4.923v-4.896q0-.401.294-.682t.669-.281v0q.401 0 .682.281t.281.682v4.896h4.923q.401 0 .682.281t.281.682v0q0 .375-.281.669t-.682.294z" /> + </SvgIcon> + ); +} + +function CloseSquare(props: SvgIconProps) { + return ( + <SvgIcon className="close" fontSize="inherit" style={{ width: 14, height: 14 }} {...props}> + {/* tslint:disable-next-line: max-line-length */} + <path d="M17.485 17.512q-.281.281-.682.281t-.696-.268l-4.12-4.147-4.12 4.147q-.294.268-.696.268t-.682-.281-.281-.682.294-.669l4.12-4.147-4.12-4.147q-.294-.268-.294-.669t.281-.682.682-.281.696 .268l4.12 4.147 4.12-4.147q.294-.268.696-.268t.682.281 .281.669-.294.682l-4.12 4.147 4.12 4.147q.294.268 .294.669t-.281.682zM22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0z" /> + </SvgIcon> + ); +} + +function ServerIcon(props: SvgIconProps) { + return ( + <SvgIcon fontSize="inherit" style={{ width: 14, height: 14 }} {...props}> + {/* tslint:disable-next-line: max-line-length */} + <path d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 12.977h-4.923v4.896q0 .401-.281.682t-.682.281v0q-.375 0-.669-.281t-.294-.682v-4.896h-4.923q-.401 0-.682-.294t-.281-.669v0q0-.401.281-.682t.682-.281h4.923v-4.896q0-.401.294-.682t.669-.281v0q.401 0 .682.281t.281.682v4.896h4.923q.401 0 .682.281t.281.682v0q0 .375-.281.669t-.682.294z" /> + </SvgIcon> + ); +} + +function UpdateIcon(props: SvgIconProps) { + return ( + <SvgIcon fontSize="inherit" style={{ width: 14, height: 14 }} {...props}> + {/* tslint:disable-next-line: max-line-length */} + <path d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 12.977h-4.923v4.896q0 .401-.281.682t-.682.281v0q-.375 0-.669-.281t-.294-.682v-4.896h-4.923q-.401 0-.682-.294t-.281-.669v0q0-.401.281-.682t.682-.281h4.923v-4.896q0-.401.294-.682t.669-.281v0q.401 0 .682.281t.281.682v4.896h4.923q.401 0 .682.281t.281.682v0q0 .375-.281.669t-.682.294z" /> + </SvgIcon> + ); +} + +function PackageIcon(props: SvgIconProps) { + return ( + <SvgIcon fontSize="inherit" style={{ width: 14, height: 14 }} {...props}> + {/* tslint:disable-next-line: max-line-length */} + <path d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 12.977h-4.923v4.896q0 .401-.281.682t-.682.281v0q-.375 0-.669-.281t-.294-.682v-4.896h-4.923q-.401 0-.682-.294t-.281-.669v0q0-.401.281-.682t.682-.281h4.923v-4.896q0-.401.294-.682t.669-.281v0q.401 0 .682.281t.281.682v4.896h4.923q.401 0 .682.281t.281.682v0q0 .375-.281.669t-.682.294z" /> + </SvgIcon> + ); +} + +function CorrectionIcon(props: SvgIconProps) { + return ( + <SvgIcon fontSize="inherit" style={{ width: 14, height: 14 }} {...props}> + {/* tslint:disable-next-line: max-line-length */} + <path d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 12.977h-4.923v4.896q0 .401-.281.682t-.682.281v0q-.375 0-.669-.281t-.294-.682v-4.896h-4.923q-.401 0-.682-.294t-.281-.669v0q0-.401.281-.682t.682-.281h4.923v-4.896q0-.401.294-.682t.669-.281v0q.401 0 .682.281t.281.682v4.896h4.923q.401 0 .682.281t.281.682v0q0 .375-.281.669t-.682.294z" /> + </SvgIcon> + ); +} + +const tableIcons = { + Add: React.forwardRef<SVGSVGElement>((props, ref) => ( + <AddBox {...props} ref={ref} /> + )), + Check: React.forwardRef<SVGSVGElement>((props, ref) => ( + <Check {...props} ref={ref} /> + )), + Clear: React.forwardRef<SVGSVGElement>((props, ref) => ( + <Clear {...props} ref={ref} /> + )), + Delete: React.forwardRef<SVGSVGElement>((props, ref) => ( + <Delete {...props} ref={ref} /> + )), + DetailPanel: React.forwardRef<SVGSVGElement>((props, ref) => ( + <ChevronRight {...props} ref={ref} /> + )), + Edit: React.forwardRef<SVGSVGElement>((props, ref) => ( + <Edit {...props} ref={ref} /> + )), + Export: React.forwardRef<SVGSVGElement>((props, ref) => ( + <SaveAlt {...props} ref={ref} /> + )), + Filter: React.forwardRef<SVGSVGElement>((props, ref) => ( + <FilterList {...props} ref={ref} /> + )), + FirstPage: React.forwardRef<SVGSVGElement>((props, ref) => ( + <FirstPage {...props} ref={ref} /> + )), + LastPage: React.forwardRef<SVGSVGElement>((props, ref) => ( + <LastPage {...props} ref={ref} /> + )), + NextPage: React.forwardRef<SVGSVGElement>((props, ref) => ( + <ChevronRight {...props} ref={ref} /> + )), + PreviousPage: React.forwardRef<SVGSVGElement>((props, ref) => ( + <ChevronLeft {...props} ref={ref} /> + )), + ResetSearch: React.forwardRef<SVGSVGElement>((props, ref) => ( + <Clear {...props} ref={ref} /> + )), + Search: React.forwardRef<SVGSVGElement>((props, ref) => ( + <Search {...props} ref={ref} /> + )), + SortArrow: React.forwardRef<SVGSVGElement>((props, ref) => ( + <ArrowDownward {...props} ref={ref} /> + )), + ThirdStateCheck: React.forwardRef<SVGSVGElement>((props, ref) => ( + <Remove {...props} ref={ref} /> + )), + ViewColumn: React.forwardRef<SVGSVGElement>((props, ref) => ( + <ViewColumn {...props} ref={ref} /> + )), +}; + +export const rpoInfoIcons = { + table: tableIcons, + filterList: FilterList, + minusSquare: < MinusSquare />, + plusSquare: < PlusSquare />, + closeSquare: < CloseSquare />, + arrowDropDown: <ArrowDropDownIcon />, + arrowRight: <ArrowRightIcon />, + typePath: (type: number): any => { + switch (type) { + case 1: //UPDATE + return <UpdateIcon /> + case 2: //PACKAGE + return <PackageIcon /> + case 3: //CORRRECTION + return <CorrectionIcon /> + default: + return <ServerIcon /> + } +} +}; diff --git a/src/rpoInfo/helper/theme.tsx b/src/rpoInfo/helper/theme.tsx new file mode 100644 index 00000000..75510d27 --- /dev/null +++ b/src/rpoInfo/helper/theme.tsx @@ -0,0 +1,109 @@ +import * as React from "react"; +import { createMuiTheme, createStyles, lighten, makeStyles, Theme, ThemeProvider } from "@material-ui/core/styles"; +import { CssBaseline } from "@material-ui/core"; + +interface IRpoInfoThemeProps { + children: any; +} + +export default function RpoInfoTheme(props: IRpoInfoThemeProps) { + const darkMode = false; //useMediaQuery("(prefers-color-scheme: dark)"); + + const theme = React.useMemo( + () => + createMuiTheme({ + palette: { + type: darkMode ? "dark" : "light", + }, + overrides: { + MuiPaper: { + root: { + backgroundColor: "#FDFDFD", + padding: 6, + }, + outlined: { + borderLeftStyle: "solid", + borderLeftWidth: 5, + borderLeftColor: "#EA9B3E", + }, + }, + MuiDialog: { + paper: { + backgroundColor: "#FDFDFD", + }, + }, + MuiCard: {}, + MuiCardHeader: { + root: {}, + title: { + color: "silver", + fontSize: "medium", + }, + }, + }, + }), + [darkMode] + ); + + return ( + <ThemeProvider theme={theme}> + <CssBaseline /> + {props.children} + </ThemeProvider> + ); +} + +export const useToolbarStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + paddingLeft: theme.spacing(1), + paddingRight: theme.spacing(1), + }, + highlight: + theme.palette.type === "light" + ? { + color: theme.palette.secondary.main, + backgroundColor: lighten(theme.palette.secondary.light, 0.85), + } + : { + color: theme.palette.text.primary, + backgroundColor: theme.palette.secondary.dark, + }, + title: { + display: "inline", + fontSize: "180%", + fontWeight: "bold", + marginLeft: "16px", + }, + subtitle: { + color: "silver", + display: "inline", + marginLeft: "20px", + }, + actions: { + display: "inline", + marginRight: "8px", + float: "right", + }, + actionOn: { + borderRadius: "25px", + border: "2px solid silver", + boxShadow: "0 0 3px #FF0000, 0 0 5px #0000FF", + }, + }) +); + +export const inputTextStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + display: 'flex', + flexWrap: 'wrap', + }, + textField: { + marginLeft: theme.spacing(0.5), + marginRight: theme.spacing(0.5), + width: '20ch', + }, + }), +); + diff --git a/src/rpoInfo/index.ts b/src/rpoInfo/index.ts new file mode 100644 index 00000000..6c35c399 --- /dev/null +++ b/src/rpoInfo/index.ts @@ -0,0 +1,3 @@ +import { RpoInfoLoader } from "./rpoInfoLoader"; + +export { RpoInfoLoader as CreateRpoInfoLoader }; diff --git a/src/rpoInfo/rpoInfoLoader.ts b/src/rpoInfo/rpoInfoLoader.ts new file mode 100644 index 00000000..372891fc --- /dev/null +++ b/src/rpoInfo/rpoInfoLoader.ts @@ -0,0 +1,312 @@ +import * as vscode from "vscode"; +import * as path from "path"; +import { sendRpoInfo } from "../protocolMessages"; +import { RpoInfoPanelAction, IRpoInfoPanelAction } from "./actions"; +import { ServerItem } from "../serverItemProvider"; +import * as nls from "vscode-nls"; +import Utils from "../utils"; +import { languageClient } from "../extension"; +import { IProgramApp, IRpoInfoData, IRpoPatch } from "./rpoPath"; + +const localize = nls.loadMessageBundle(); + +let rpoInfoLoader: RpoInfoLoader = undefined; + +export function openRpoInfoView(context: vscode.ExtensionContext) { + const server = Utils.getCurrentServer(); + + if ((rpoInfoLoader === null) || (rpoInfoLoader == undefined)) { + rpoInfoLoader = new RpoInfoLoader(context); + } + + rpoInfoLoader.toggleServerToMonitor(server); +} + +export class RpoInfoLoader { + protected readonly _panel: vscode.WebviewPanel | undefined; + private readonly _extensionPath: string; + private _disposables: vscode.Disposable[] = []; + private _isDisposed: boolean = false; + private _monitorServer: any = null; + private _context: vscode.ExtensionContext; + + public get monitorServer(): any { + return this._monitorServer; + } + + public set monitorServer(value: any) { + if (this._monitorServer !== value) { + this._monitorServer = value; + this.updateRpoInfo(); + } + } + + constructor(context: vscode.ExtensionContext) { + const ext = vscode.extensions.getExtension("TOTVS.tds-vscode"); + this._extensionPath = ext.extensionPath; + this._context = context; + + this._disposables.push( + Utils.onDidSelectedServer((newServer: ServerItem) => { + rpoInfoLoader.toggleServerToMonitor(newServer); + }) + ); + + this._panel = vscode.window.createWebviewPanel( + "rpoInfoLoader", + localize("RPO_LOG", "Log do repositório"), + vscode.ViewColumn.One, + { + enableScripts: true, + localResourceRoots: [ + vscode.Uri.file(path.join(this._extensionPath, "out", "webpack")), + ], + } + ); + + this._panel.webview.html = this.getWebviewContent(); + this._panel.onDidChangeViewState( + (listener: vscode.WebviewPanelOnDidChangeViewStateEvent) => { + }, + undefined, + this._disposables + ); + + this._panel.webview.onDidReceiveMessage( + (command: IRpoInfoPanelAction) => { + this.handleMessage(command); + }, + undefined, + this._disposables + ); + + this._panel.onDidDispose((event) => { + this._isDisposed = true; + + rpoInfoLoader = undefined; + }); + } + + public toggleServerToMonitor(serverItem: ServerItem) { + this.monitorServer = null; + + if (serverItem) { + this.monitorServer = serverItem; + } + } + + private async handleMessage(command: IRpoInfoPanelAction) { + switch (command.action) { + case RpoInfoPanelAction.ExportToJson: { + this.updateStatus( + localize("EXPORT_JSON", "Waiting for export JSON file") + ); + + break; + } + case RpoInfoPanelAction.ExportToTxt: { + vscode.window.setStatusBarMessage( + "$(clock)" + + "Export repository log. Wait...", + this.doExportToTxt(this.monitorServer, command.content.rpoInfo, command.content.rpoPath). + then((filename: string) => { + var setting: vscode.Uri = vscode.Uri.parse("file:" + filename); + vscode.workspace.openTextDocument(setting).then((a: vscode.TextDocument) => { + vscode.window.showTextDocument(a, 1, false); + }, (error: any) => { + vscode.window.showErrorMessage(error); + }); + }, (reason: any) => { + vscode.window.showErrorMessage(reason); + }) + ); + + break; + } + default: + console.log("***** ATTENTION: rpoInfoLoader.tsx"); + console.log("\tUnrecognized command: " + command.action); + console.log("\t" + command.content); + break; + } + } + + public doExportToTxt(server: any, rpoInfo: any, rpoPath: IRpoPatch): Thenable<string> { + return new Promise<string>((resolve, reject) => { + const fs = require('fs'); + const tmp = require('tmp'); + const file = tmp.fileSync({ prefix: "vscode-tds-rpo", postfix: ".log" }); + + const writeLine = (line: string) => { + fs.appendFileSync(file.fd, line); + fs.appendFileSync(file.fd, '\n'); + } + const SEPARATOR_LINE = '-'.repeat(50); + + writeLine(SEPARATOR_LINE); + writeLine(`Server ........: ${server.name}`); + writeLine(`Port ..........: ${server.port}`); + writeLine(`Address .......: ${server.address}`); + writeLine(`Build .........: ${server.buildVersion}`); + writeLine(`OS Platform ...: ${server.osType}`); + writeLine(SEPARATOR_LINE); + + writeLine(`Environment ...: ${rpoInfo.environment}`); + writeLine(` RPO Version..: ${rpoInfo.version}`); + writeLine(` Generated at : ${rpoInfo.date}`); + writeLine(SEPARATOR_LINE); + + writeLine(`File`); + writeLine(` Applyed .....: ${rpoPath.typePatch == 1 ? "Update" : rpoPath.typePatch == 2 ? "Package" : "Correction"}`); + writeLine(` Build .......: ${rpoPath.buildFileApplication}`); + writeLine(` Date ........: ${rpoPath.dateFileApplication}`); + writeLine(SEPARATOR_LINE); + + writeLine(`Generation`); + writeLine(` Build .......: ${rpoPath.buildFileGeneration}`); + writeLine(` Date ........: ${rpoPath.dateFileGeneration}`); + writeLine(SEPARATOR_LINE); + + if (rpoPath.skipOld) { + writeLine("This file overwrote more recent resources"); + writeLine(SEPARATOR_LINE); + } + + rpoPath.programsApp.forEach((value: IProgramApp) => { + writeLine(value.name.padEnd(29, " ") + "\t" + value.date); + }) + writeLine(SEPARATOR_LINE); + + const ext = vscode.extensions.getExtension("TOTVS.tds-vscode"); + const now = new Date().toLocaleString(); + + writeLine(""); + writeLine(SEPARATOR_LINE); + writeLine(`Total resources: ${rpoPath.programsApp.length}`); + writeLine(`Generated by TDS-VSCode version${ext.packageJSON["version"]}`); + writeLine(`at ${now}`); + writeLine(SEPARATOR_LINE); + + return resolve(file.name); + }) + } + + public updateRpoInfo() { + if (this.monitorServer === null) { + return; + } + + vscode.window.setStatusBarMessage( + "$(clock)" + + localize( + "REQUESTING_DATA_FROM_SERVER", + "Requesting data from the server [{0}]", + this.monitorServer.name + ), + sendRpoInfo(this.monitorServer).then( + (rpoInfo: IRpoInfoData) => { + this._panel.webview.postMessage({ + command: RpoInfoPanelAction.UpdateRpoInfo, + data: { + serverName: this.monitorServer.name, + rpoInfo: rpoInfo, + }, + }); + }, + (err: Error) => { + languageClient.error(err.message, err); + vscode.window.showErrorMessage( + err.message + localize("SEE_LOG", ". See log for details.") + ); + } + ) + ); + } + + private updateStatus(msg: string) { + let icon: string = "$(clock)"; + + vscode.window.setStatusBarMessage(`${icon} ${msg}`); + } + + private getWebviewContent(): string { + // Local path to main script run in the webview + const reactAppPathOnDisk = vscode.Uri.file( + path.join(this._extensionPath, "out", "webpack", "rpoInfoPanel.js") + ); + + const servers: ServerItem[] = this.monitorServer + ? [this.monitorServer] + : []; + + const reactAppUri = this._panel?.webview.asWebviewUri(reactAppPathOnDisk); + const configJson: any = { + serverList: servers, + translations: getTranslations(), + }; + + return `<!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Monitor View + + + + + + +
+ + + `; + } +} + +function getTranslations() { + return { + NO_INFO_FROM_RPO: localize( + "NO_INFO_FROM_RPO", + "There is no information about the RPO." + ), + ACTIONS: localize("ACTIONS", "Actions"), + DRAG_HEADERS: localize("DRAG_HEADERS", "Drag headers ..."), + FILTER: localize("FILTER", "Filter"), + FILTERING_ON_OFF: localize("FILTERING_ON_OFF", "Filtering on/off"), + FIRST: localize("FIRST", "First"), + FIRST_PAGE: localize("FIRST_PAGE", "First page"), + FROM_TO_OF_COUNT: localize("FROM_TO_OF_COUNT", "from-to de count"), + GROUPED_BY: localize("GROUPED_BY", "Grouped by:"), + GROUPING_ON_OFF: localize("GROUPING_ON_OFF", "Grouping on/off"), + TREE_ON_OFF: localize("TREE_ON_OFF", "Tree server on/off"), + LAST: localize("LAST", "Last"), + LAST_PAGE: localize("LAST_PAGE", "Last page"), + LINES_PAGE: localize("LINES_PAGE", "lines/p."), + NEXT: localize("NEXT", "Next"), + NEXT_PAGE: localize("NEXT_PAGE", "Next page"), + PREVIOUS: localize("PREVIOUS", "Previous"), + PREVIOUS_PAGE: localize("PREVIOUS_PAGE", "Previous page"), + RESET_CONFIGURATIONS: localize( + "RESET_CONFIGURATIONS", + "Reset configurations" + ), + SEARCH: localize("SEARCH", "Search"), + SEARCH_ALL_COLUMNS: localize("SEARCH_ALL_COLUMNS", "Search in all columns"), + SERVER: localize("SERVER", "Server"), + SHOW_HIDE_COLUMNS: localize("SHOW_HIDE_COLUMNS", "Show/hide columns"), + INITIALIZING: localize("INITIALIZING", "(initializing)"), + SHOW_COLUMNS: localize("SHOW_COLUMNS", "Show Columns"), + RESOURCES: localize("RESOURCES", "Resources"), + EXPORT_TXT: localize("EXPORT_TXT", "Export as Text"), + RPO_LOG: localize("RPO_LOG", "Repository Log") + + }; +} diff --git a/src/rpoInfo/rpoPath.ts b/src/rpoInfo/rpoPath.ts new file mode 100644 index 00000000..89336cc1 --- /dev/null +++ b/src/rpoInfo/rpoPath.ts @@ -0,0 +1,21 @@ +export interface IProgramApp { + name: string; + date: string; +} + +export interface IRpoPatch { + dateFileGeneration: string; + buildFileGeneration: string; + dateFileApplication: string; + buildFileApplication: string; + skipOld: boolean; + typePatch: number; + programsApp: IProgramApp[]; +} + +export interface IRpoInfoData { + rpoVersion: string; + dateGeneration: string; + environment: string; + rpoPatchs: IRpoPatch[]; +} diff --git a/src/utils.ts b/src/utils.ts index 96a24a5c..e235ed14 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,6 +7,7 @@ import * as ini from "ini"; import * as nls from "vscode-nls"; import { languageClient } from "./extension"; import { EnvSection, ServerItem } from "./serverItemProvider"; +import { Authorization, CompileKey } from "./compileKey/compileKey"; const homedir = require("os").homedir(); const localize = nls.loadMessageBundle(); @@ -46,7 +47,7 @@ export default class Utils { /** * Subscrição para evento de chave de compilação. */ - static get onDidSelectedKey(): vscode.Event { + static get onDidSelectedKey(): vscode.Event { return Utils._onDidSelectedKey.event; } @@ -58,7 +59,7 @@ export default class Utils { /** * Emite a notificação de seleção de chave de compilação */ - private static _onDidSelectedKey = new vscode.EventEmitter(); + private static _onDidSelectedKey = new vscode.EventEmitter(); /** * Gera um id de servidor @@ -464,18 +465,13 @@ export default class Utils { } } - static getPermissionsInfos() { + static getPermissionsInfos(): CompileKey { const servers = Utils.getServersConfig(); - const permissions = servers.permissions; - if (permissions) { - return permissions; - } - - return ""; + return servers ? servers.permissions : undefined; } - static savePermissionsInfos(infos: any) { + static savePermissionsInfos(infos: CompileKey) { const config = Utils.getServersConfig(); config.permissions = infos; @@ -484,6 +480,15 @@ export default class Utils { Utils._onDidSelectedKey.fire(infos); } + static deletePermissionsInfos() { + const config = Utils.getServersConfig(); + + config.permissions = undefined; + + Utils.persistServersInfo(config); + Utils._onDidSelectedKey.fire(undefined); + } + static removeExpiredAuthorization() { vscode.window.showWarningMessage( localize( @@ -491,7 +496,7 @@ export default class Utils { "Expired authorization token deleted" ) ); - Utils.savePermissionsInfos({}); // remove expired authorization key + Utils.deletePermissionsInfos(); // remove expired authorization key } /** @@ -783,10 +788,9 @@ export default class Utils { return result; } - static readCompileKeyFile(path) { + static readCompileKeyFile(path): Authorization { if (fs.existsSync(path)) { - const parseIni = ini.parse(fs.readFileSync(path, "utf-8").toLowerCase()); - + const parseIni = ini.parse(fs.readFileSync(path, "utf-8").toLowerCase()); // XXX toLowerCase?? return parseIni.authorization; } return undefined; diff --git a/webpack.config.js b/webpack.config.js index 8cdc18a0..c4338fa2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,23 +1,23 @@ const path = require("path"); -const TerserPlugin = require('terser-webpack-plugin'); +const TerserPlugin = require("terser-webpack-plugin"); -const REPLAY_PATH = path.join(__dirname,'./src/debug/tdsreplay/'); -const MONITOR_PATH = path.join(__dirname,'./src/monitor/'); +const REPLAY_PATH = path.join(__dirname, "./src/debug/tdsreplay/"); +const MONITOR_PATH = path.join(__dirname, "./src/monitor/"); +const RPO_INFO_PATH = path.join(__dirname, "./src/rpoInfo/"); module.exports = { target: "node", optimization: { minimize: false, - minimizer: [ - new TerserPlugin(), - ], + minimizer: [new TerserPlugin()], }, - //O webpack, pega todos os fontes tsx e os compacta em um unico arquivo .js. Isso é feito para contornar algumas limitações e alguns browsers que não aceitam a instrução import. + //O webpack, pega todos os fontes tsx e os compacta em um unico arquivo .js. Isso é feito para contornar algumas limitações e alguns browsers que não aceitam a instrução import. //O entry pode ser definido com um objeto. A chave, ou no nome da propriedade, nesse caso sera o nome de saida do arquivo. entry: { timeLineView: path.join(REPLAY_PATH, "app/index.tsx"), monitorPanel: path.join(MONITOR_PATH, "app/index.tsx"), + rpoInfoPanel: path.join(RPO_INFO_PATH, "app/index.tsx"), }, output: { //Todos os arquivos tsx serão compilados e gerados seus equivalentes js na mesma pasta @@ -32,20 +32,38 @@ module.exports = { vscode: "commonjs vscode", }, resolve: { - extensions: [".js", ".ts", ".tsx", ".json", ".bundle.json", ".bundle.*.json"], + extensions: [ + ".js", + ".ts", + ".tsx", + ".json", + ".bundle.json", + ".bundle.*.json", + ], }, module: { rules: [ { test: /\.(ts|tsx)$/, - //exclude: /node_modules/, include: REPLAY_PATH, use: [ { loader: "ts-loader", options: { - configFile: path.join(REPLAY_PATH, './app/tsconfig.json'), - } + configFile: path.join(REPLAY_PATH, "./app/tsconfig.json"), + }, + }, + ], + }, + { + test: /\.(ts|tsx)$/, + include: RPO_INFO_PATH, + use: [ + { + loader: "ts-loader", + options: { + configFile: path.join(RPO_INFO_PATH, "./app/tsconfig.json"), + }, }, ], }, @@ -56,8 +74,8 @@ module.exports = { { loader: "ts-loader", options: { - configFile: path.join(MONITOR_PATH, './app/tsconfig.json'), - } + configFile: path.join(MONITOR_PATH, "./app/tsconfig.json"), + }, }, ], },